【问题标题】:SQL - Matching only the values in IN clause (not less or more)SQL - 仅匹配 IN 子句中的值(不是更少或更多)
【发布时间】:2020-07-22 15:14:49
【问题描述】:

我有以下多对多表TEAM_USERS,其中包含以下数据:

TEAM_ID     USER_ID
1           10
1           3
1           4
1           11
12          10
12          3
12          4
11          3
11          4
18          10
18          7
18          4
18          11

所以,我想获得只有两个用户的 USER_ID IN (3、4) 的 TEAM_ID,在这种情况下是团队 11。但我得到的是团队 1、11 和 12。我只想要第 11 队。

我执行了以下代码,但没有得到预期的结果

SELECT  team_id
FROM    team_users 
WHERE   user_profile_id IN (3 , 4)
GROUP   BY team_id
HAVING  COUNT(DISTINCT user_profile_id) = 2;

这个查询的结果是:

TEAM_ID
1
11
12

所以,任何帮助将不胜感激。

=============== 编辑:列表是唯一的,没有重复

【问题讨论】:

    标签: sql database oracle where-clause having-clause


    【解决方案1】:

    将 WHERE 条件移入 条件聚合

    只要组合 team_id/user_profile_id 是唯一的:

    select team_id
    from team_users 
    group by team_id
    -- exactly those two and no other
    having sum(case when user_profile_id in (3, 4) then 1 else -1 end) = 2
    

    【讨论】:

    • 是的,组合是唯一的,这就是为什么我想获取 team_id 以防止重复。感谢您的帮助。
    【解决方案2】:

    您的where 子句在您有机会考虑之前过滤掉user_profile_id 不是34 的行。您可以将逻辑移至 having 子句,例如:

    select team_id
    from team_users 
    group by team_id
    having  
        sum(case when user_profile_id in (3, 4) then 1 else 0 end) = 2
        and sum(case when user_profile not in (3, 4) then 1 else 0 end) = 0
    

    这假设 (team_id, user_profile_id) 元组在您的数据中是唯一的,如您的示例数据中所示。

    【讨论】:

    • 没有重复项,您的解决方案运行良好。感谢您的帮助。
    【解决方案3】:

    将所有过滤移至where 子句:

    SELECT team_id
    FROM team_users 
    GROUP BY team_id
    HAVING COUNT(*) = 2 AND
           SUM(CASE WHEN user_profile_id IN (3 , 4) THEN 1 ELSE 0 END) = 2;
    

    这会检查有两个成员并且他们是两个指定的成员。此外,这假设没有重复,这似乎是合理的。

    如果列表不太大,您也可以使用LISTAGG() 表达这一点:

    SELECT team_id
    FROM team_users 
    GROUP BY team_id
    HAVING LISTAGG(user_profile_id, ',') WITHIN GROUP (ORDER BY user_profile_id) = '3,4';
    

    【讨论】:

    • 我会更进一步,做COUNT(*) = SUM(CASE WHEN user_profile_id IN (3 , 4) THEN 1 ELSE 0 END) - 没有理由计算in 子句中的项目数......
    • @ZoharPeled:这也将返回一个只有 3 个 4 个存在的团队
    • @Gordon 感谢分享知识,效果很好。
    【解决方案4】:

    您可以为 where 子句提供 AND 条件以获取 team_id = 11 的结果

    SELECT  team_id
    FROM    team_users 
    WHERE   user_profile_id IN (3 , 4) AND team_id = 11
    GROUP   BY team_id
    HAVING  COUNT(DISTINCT user_profile_id) = 2;
    

    我没有类似的测试数据库设置,所以你可能想运行并检查它

    【讨论】:

    • team_id = 11 ,是我想要得到的,所以我已经没有将它作为参数传递的 team_id
    猜你喜欢
    • 1970-01-01
    • 2017-05-28
    • 2012-07-23
    • 2015-01-25
    • 2023-03-24
    • 1970-01-01
    • 2012-01-28
    • 2023-01-15
    • 1970-01-01
    相关资源
    最近更新 更多