sqlpartition

Filter with partition SQL


I have this data as a tree:

Id name t1 t2 t3 fullT
1 A 59 null null 59
2 B 59 20 null 59.02
3 C 59 40 null 59.04
4 D 59 60 null 59.06
5 E 59 60 01 59.060.01
6 F 59 60 10 59.060.10

as I mentioned the table is a tree so t1 is the parent and t2 is the first child and t3 is the second child. so if the t2 and t3 are null means it is the parent.

                     59
    /                |              \
   20               40              60
                                   /  \
                                 01   10

and this is the result I expect:

Id name t1 t2 t3 fullT
1 A 59.A null null 59
2 B 59.A 020.B null 59.02
3 C 59.A 040.C null 59.04
4 D 59.A 060.D null 59.06
5 E 59.A 060.D 01.E 59.060.01
6 F 59.A 060.D 10.F 59.060.10

to make it readable I want to concatenate between each (t) and its name as shown in the previous table, so I have created this query.

SELECT 
    Id,
    name,
    MAX(CASE WHEN t2 = '' AND t3 = '' THEN CONCAT([t1],'.', [ICSAr]) ELSE null END) OVER (PARTITION BY t1) AS t1,
    MAX(CASE WHEN t1 != '' AND t3 = ''  AND t2 != '' THEN CONCAT([t2],'.', [name]) ELSE NULL END) OVER (PARTITION BY t1,[t2]) AS t2,
    CASE WHEN [t3] != '' THEN CONCAT([t3],'.', [name]) END AS [t3]
FROM [table]

but if I use a where condition based on t2 or t3, the result is not correct because it gives the result based on the condition. ex
1- WHERE t1= 59 and t2 = 020

Id name t1 t2 t3
2 B null 020.B null

the result I expect is:

Id name t1 t2 t3
2 B 59.A 020.B null

2- WHERE t1= 59 and t3 = 10

Id name t1 t2 t3
6 F Null Null 10.F

the result I expect is:

Id name t1 t2 t3
6 F 59.A 060.D 10.F

how can I make the query over all the tables even if there are conditions?


Solution

  • Assuming SQL Server, you can use FIRST_VALUE() as NULLs are ordered first.

    It's similar to using MAX(CASE WHEN x IS NULL THEN name END) in a window.

    Both versions are below...

    CREATE TABLE your_table (
      id                INT,
      name              CHAR,
      t1                INT,
      t2                INT,
      t3                INT,
      fullT             VARCHAR(11)
    )
    
    INSERT INTO
      your_table
    VALUES
      (1, 'A', 59,  null, null, '59'),
      (2, 'B', 59,  20,   null, '59.02'),
      (3, 'C', 59,  40,   null, '59.04'),
      (4, 'D', 59,  60,   null, '59.06'),
      (5, 'E', 59,  60,   01,   '59.060.01'),
      (6, 'F', 59,  60,   10,   '59.060.10')
    
    WITH
      name_lookup AS
    (
      SELECT
        id,
        name,
        t1, t2, t3,
        FIRST_VALUE(name) OVER (PARTITION BY t1         ORDER BY t1, t2, t3)  AS name1,
        FIRST_VALUE(name) OVER (PARTITION BY t1, t2     ORDER BY t1, t2, t3)  AS name2,
        FIRST_VALUE(name) OVER (PARTITION BY t1, t2, t3 ORDER BY t1, t2, t3)  AS name3
      FROM
        your_table
    )
    SELECT
        id,
        name,
        t1, t2, t3,
        CASE WHEN t1 IS NOT NULL THEN name1 END   AS name1,
        CASE WHEN t2 IS NOT NULL THEN name2 END   AS name2,
        CASE WHEN t3 IS NOT NULL THEN name3 END   AS name3
    FROM
      name_lookup
    ORDER BY
      id
    
    id name t1 t2 t3 name1 name2 name3
    1 A 59 null null A null null
    2 B 59 20 null A B null
    3 C 59 40 null A C null
    4 D 59 60 null A D null
    5 E 59 60 1 A D E
    6 F 59 60 10 A D F
    WITH
      name_lookup AS
    (
      SELECT
        id,
        name,
        t1, t2, t3,
        MAX(CASE WHEN t2 IS NULL THEN name ELSE NULL END) OVER (PARTITION BY t1        )  AS name1,
        MAX(CASE WHEN t3 IS NULL THEN name ELSE NULL END) OVER (PARTITION BY t1, t2    )  AS name2,
        MAX(                          name              ) OVER (PARTITION BY t1, t2, t3)  AS name3
      FROM
        your_table
    )
    SELECT
        id,
        name,
        t1, t2, t3,
        CASE WHEN t1 IS NOT NULL THEN name1 END   AS name1,
        CASE WHEN t2 IS NOT NULL THEN name2 END   AS name2,
        CASE WHEN t3 IS NOT NULL THEN name3 END   AS name3
    FROM
      name_lookup
    ORDER BY
      id
    
    id name t1 t2 t3 name1 name2 name3
    1 A 59 null null A null null
    2 B 59 20 null A B null
    3 C 59 40 null A C null
    4 D 59 60 null A D null
    5 E 59 60 1 A D E
    6 F 59 60 10 A D F

    fiddle