4

我有以下表格:

User_Group

id  group_id  group_type
------------------------
1   100       A
1   100       B
2   101       B
2   102       A

Group_A

id   name
---------
100  A
101  B
102  C

Group_B

id   name
---------
100  D
101  E
102  F

我想要所有用户的组名(使用array.agg())。如果用户的组类型 = A,我们必须从组 A 中获取组名,如果用户的组类型 = B,我们必须从组 B 中获取组名。结果应该是:

userid  groups
--------------
1       A,D
2       E,C

我为此创建了一个小提琴,并给出了一个使用 2 个单独查询联合的解决方案。可以在没有联合的情况下完成吗,我可以在其中决定从哪个表中选择组名,只需加入user_groups,group_Agroup_B

4

2 回答 2

8
select ug.id, array_agg(
    case ug.group_type 
        when 'A' then g_a.name 
        when 'B' then g_b.name 
        else 'N/A' 
    end)
from user_groups ug
left outer join group_A g_a on ug.group_id = g_a.id
left outer join group_B g_b on ug.group_id = g_b.id
group by ug.id

SQL 小提琴示例

于 2012-10-23T14:30:02.700 回答
6

你可以在没有联合的情况下使用左连接来做到这一点(我建议无论如何都使用显式连接,因为隐式连接已经过时 20 年了Aaron Bertrand 写了一篇很好的博客来解释为什么)。Group_Type 可以成为连接条件,这意味着只有在找到正确的组类型时才连接表:

SELECT  ug.ID, ARRAY_AGG(COALESCE(a.Name, b.Name))
FROM    User_Groups ug
        LEFT JOIN group_A a
            ON a.ID = ug.group_ID
            AND ug.Group_Type = 'A'
        LEFT JOIN group_B b
            ON b.ID = ug.group_ID
            AND ug.Group_Type = 'B'
WHERE   COALESCE(a.ID, b.ID) IS NOT NULL -- ENSURE AT LEAST ONE GROUP IS MATCHED
GROUP BY ug.ID;

但是,我倾向于使用 UNION Still,但将其移动如下:

SELECT  ug.ID, ARRAY_AGG(Name)
FROM    User_Groups ug
        INNER JOIN
        (   SELECT  'A' AS GroupType, ID, Name
            FROM    Group_A
            UNION ALL
            SELECT  'B' AS GroupType, ID, Name
            FROM    Group_B
        ) G
            ON g.GroupType = ug.Group_Type
            AND g.ID = ug.Group_ID
GROUP BY ug.ID;

您添加了我的查询的小提琴

于 2012-10-23T14:39:19.390 回答