SQL “tree-like” query - most parent group

后端 未结 6 1215
悲&欢浪女
悲&欢浪女 2020-12-09 07:22

I\'m having some trouble doing a \"tree-like\" query (what do we call this?) in SQL.

Take a look at my diagram below (table and column names are in danish - sorry ab

6条回答
  •  粉色の甜心
    2020-12-09 07:40

    You can use CTE's to construct "the full path" column on the fly

    --DROP TABLE Gruppe, Kunde, Gruppe_Gruppe, Kunde_Gruppe
    CREATE TABLE Gruppe (
        Id                  INT PRIMARY KEY
        , Name              VARCHAR(100)
        )
    CREATE TABLE Kunde (
        Id                  INT PRIMARY KEY
        , Name              VARCHAR(100)
        )
    CREATE TABLE Gruppe_Gruppe (
        ParentGruppeId      INT
        , ChildGruppeId     INT
        )
    CREATE TABLE Kunde_Gruppe (
        KundeId             INT
        , GruppeId          INT
        )
    
    INSERT      Gruppe
    VALUES      (1, 'Group 1'), (2, 'Group 2'), (3, 'Group 3')
                , (4, 'Sub-group A'), (5, 'Sub-group B'), (6, 'Sub-group C'), (7, 'Sub-group D')
    
    INSERT      Kunde
    VALUES      (1, 'Kunde 1'), (2, 'Kunde 2'), (3, 'Kunde 3')
    
    INSERT      Gruppe_Gruppe
    VALUES      (1, 4), (1, 5), (1, 7)
                , (2, 6), (2, 7)
                , (6, 1)
    
    INSERT      Kunde_Gruppe
    VALUES      (1, 1), (1, 2)
                , (2, 3), (2, 4)
    
    ;WITH       CTE
    AS          (
                SELECT      CONVERT(VARCHAR(1000), REPLACE(CONVERT(CHAR(5), k.Id), ' ', 'K')) AS TheKey
                            , k.Name        AS Name
                FROM        Kunde k
    
                UNION ALL
    
                SELECT      CONVERT(VARCHAR(1000), REPLACE(CONVERT(CHAR(5), x.KundeId), ' ', 'K')
                                 + REPLACE(CONVERT(CHAR(5), g.Id), ' ', 'G')) AS TheKey
                            , g.Name
                FROM        Gruppe g
                JOIN        Kunde_Gruppe x
                ON          g.Id = x.GruppeId
    
                UNION ALL
    
                SELECT      CONVERT(VARCHAR(1000), p.TheKey + REPLACE(CONVERT(CHAR(5), g.Id), ' ', 'G')) AS TheKey
                            , g.Name
                FROM        Gruppe g
                JOIN        Gruppe_Gruppe x
                ON          g.Id = x.ChildGruppeId
                JOIN        CTE p
                ON          REPLACE(CONVERT(CHAR(5), x.ParentGruppeId), ' ', 'G') = RIGHT(p.TheKey, 5)
                WHERE       LEN(p.TheKey) < 32 * 5
                )
    SELECT      *
                , LEN(TheKey) / 5 AS Level
    FROM        CTE c
    ORDER BY    c.TheKey
    

    Performance might be sub-optimal if you have lots of reads vs rare modifications.

提交回复
热议问题