想象一下,我的数据表格如下:
ROLE_ID | USER_ID | CODE
---------------------------------
14 | USER A | 001
15 | USER A | 002
11 | USER B | 004
13 | USER D | 005
13 | USER A | 001
15 | USER B | 009
15 | USER D | 005
12 | USER C | 004
15 | USER C | 008
13 | USER D | 007
15 | USER D | 007
我想获得只有13和15个role_ids的用户ID和代码。所以基于上面的数据,我想回到以下
USER D | 005
USER D | 007
我有下面的查询,但是,它只会带回一个,而不是两个。
SELECT a.user_id, a.code
FROM my_table a
WHERE a.ROLE_ID in (13,15,11,14)
group by a.USER_ID, a.code
having sum( case when a.role_id in (13,15) then 1 else 0 end) = 2
and sum( case when a.role_id in (11,14) then 1 else 0 end) = 0
ORDER BY USER_ID
以上查询仅带来
USER D | 005
而不是
USER D | 005
USER D | 007
答案 0 :(得分:2)
有时只用英语听你自己的单词会转化为最容易阅读的SQL:
SELECT DISTINCT a.user_id, a.code
FROM my_table a
WHERE a.user_id in
(SELECT b.user_id
FROM my_table b
WHERE b.ROLE_ID = 13)
AND a.user_id in
(SELECT b.user_id
FROM my_table b
WHERE b.ROLE_ID = 15)
AND a.user_id NOT IN
(SELECT b.user_id
FROM my_table b
WHERE b.ROLE_ID NOT IN (13,15))
答案 1 :(得分:0)
我会:
SELECT a.user_id, a.code
FROM my_table a
GROUP BY a.user_id, a.code
HAVING sum(case when a.role_id in (13, 15) then 1 else 3 end) = 2
:)
答案 2 :(得分:0)
SELECT user_id, code FROM my_table
WHERE role_id = 13
INTERSECT
SELECT user_id, code FROM my_table
WHERE role_id = 15
答案 3 :(得分:0)
经EthanB的证明,您的查询完全按照您的要求运行。您的项目数据中一定有某些内容不在问题的伪造数据中。
我确实支持您在问题中执行的枢轴,但是我将其编写为单个SUM
表达式,以减少汇总数据上的迭代次数。我当然不赞成multiple subqueries on each row of the table(1,2,3)...无论优化程序是否将子查询转换为多个JOIN。
您的关键条件:
having sum( case when a.role_id in (13,15) then 1 else 0 end) = 2 and sum( case when a.role_id in (11,14) then 1 else 0 end) = 0
我的推荐:
在对汇总数据进行迭代时,您可以保持合格行的计数(+1),并在每次评估后跳转到不合格结果(+3)。这样,聚合上只有一次通过而不是两次。
SELECT USER_ID, CODE
FROM my_table
WHERE ROLE_ID IN (13,15,11,14)
GROUP BY USER_ID, CODE
HAVING SUM(CASE WHEN ROLE_ID IN (13,15) THEN 1
WHEN ROLE_ID IN (11,14) THEN 3 END) = 2
表达这些HAVING子句正在做什么的另一种方法是:
要求第一个CASE满足两次,第二个CASE从不满足。
或者,上面的HAVING子句可以写得不太优雅:
HAVING SUM(CASE ROLE_ID
WHEN 13 THEN 1
WHEN 15 THEN 1
WHEN 11 THEN 3
WHEN 14 THEN 3
END) = 2
免责声明#1::我不会在[oracle]
标签池中游泳,也没有研究如何使用PIVOT
执行此操作。
免责声明#2:我的上述建议假设ROLE_ID
在分组的USER_ID
+ CODE
聚合数据中是唯一的。附带情况:(a demo)
ROLE_ID = 13
,ROLE_ID = 13
和ROLE_ID = 15
,那么SUM当然至少为3,并且该组不符合资格。ROLE_ID = 15
和ROLE_ID = 15
,那么SUM当然为2,并且该组将被无意地限制。要应对此类情况,请设置三个单独的MAX条件。
HAVING MAX(CASE WHEN ROLE_ID = 13 THEN 1 END) = 1
AND MAX(CASE WHEN ROLE_ID = 15 THEN 1 END) = 1
AND MAX(CASE WHEN ROLE_ID IN (11,14) THEN 1 END) IS NULL