Соединить таблицу с одной таблицей, если условие 1 истинно, и с другой таблицей, если условие 1 ложно?
У меня есть следующие таблицы:
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
Я создал скрипку для этого и дал решение, используя объединение двух отдельных запросов. Можно ли это сделать без объединения, в котором я могу решить, из какой таблицы выбрать имя группы, с помощью одного объединения user_groups
, group_A
а также group_B
?
2 ответа
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
Вы можете сделать это без объединения, используя левые объединения (я бы посоветовал использовать явные объединения в любом случае, поскольку неявные объединения устарели на 20 лет. Аарон Бертран написал хороший блог о том, почему). 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;