按分组,然后在聚合列表上查询

时间:2018-10-03 18:53:08

标签: sql group-by google-bigquery

如果我有两个表:

Users      Labels
-----      ------
id           id
           user_id

和用户以及一对多的标签。

我想说的是,“给我所有具有label = 1或label = 2但不包含label = 3的用户”,因此具有标签[1,5,6]的用户将是有效的[2,5,6 ]有效,但[2,3,4]无效。

我将如何去做?我目前正在使用array_aggunnest,但我想在没有数组操作的情况下执行此操作。

WITH (
    SELECT user_id, ARRAY_AGG(id) as labels from label
) as labels_agg

SELECT id FROM users
LEFT JOIN labels_agg ON id=user_id
WHERE 1 in UNNEST(labels) and 2 in UNNEST(labels) and 3 not in UNNEST(labels)

4 个答案:

答案 0 :(得分:2)

这可以通过not exists完成。

SELECT l1.user_id, l1.id as labels 
from label l1
where id in (1,2)
and not exists (select 1 from label l2 where l1.user_id=l2.user_id and l2.id = 3)

答案 1 :(得分:2)

  

带有label = 1或label = 2,但没有label = 3

对于这种查询,我建议使用group byhaving

select l.user_id
from labels l
where l.id in (1, 2, 3)
group by l.user_id
having sum(case when l.id in (1, 2) then 1 else 0 end) > 0 and
       sum(case when l.id in (3) then 1 else 0 end) = 0 ;

带有条件聚合的having子句非常灵活。 sum(case . . . )计算每个用户ID提及的标签数。 > 0说,至少存在一个。 = 0说不存在。

在这种情况下,您实际上可以将逻辑简化为:

select l.user_id
from labels l
where l.id in (1, 2, 3)
group by l.user_id
having max(l.id) in (1, 2);

这恰好适用于这些id,但不能一概而论。

答案 2 :(得分:2)

您可以使用EXCEPT获得所需的结果。

;WITH cte AS
(
SELECT DISTINCT usr.id AS UserId, lbl.id AS Label_Id FROM Users usr LEFT 
JOIN Labels lbl ON
usr.id = lbl.[user_id] 
)
SELECT UserId FROM cte WHERE
Label_Id IN (1,2) 
EXCEPT
SELECT UserId FROM cte WHERE
Label_Id IN (3) 

这是demo

答案 3 :(得分:1)

#standardSQL
SELECT user_id
FROM labels
GROUP BY user_id
HAVING COUNTIF(id IN (1, 2)) > 0 
AND COUNTIF(id = 3) = 0