-1

想象一下,我有一个包含如下数据的表格:

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 个角色 ID 的用户 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
4

4 回答 4

4

有时只是听你自己的英文单词翻译成最容易阅读的 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))
于 2012-08-29T03:05:07.343 回答
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

:)

于 2012-08-29T06:13:15.810 回答
0

正如EthanB所证明的那样,您的查询完全按照您的意愿工作。您的项目数据中必须有某些内容未在您的问题的捏造数据中表示。

我确实支持您在问题中执行的枢轴,但我会将其写为单个SUM表达式以减少对聚合数据的迭代次数。我当然不赞成在表的每一行123)上使用多个子查询……无论优化器是否将子查询转换为多个 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_IDs 在分组USER_ID+CODE聚合数据中是唯一的。边缘案例:(演示

  1. 给定的组包含ROLE_ID = 13, ROLE_ID = 13,ROLE_ID = 15然后当然 SUM 将至少为 3 并且该组将被取消资格。
  2. 给定的组仅包含ROLE_ID = 15ROLE_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

演示

于 2020-03-07T23:21:10.293 回答
-1
SELECT user_id, code FROM my_table
WHERE role_id = 13
INTERSECT
SELECT user_id, code FROM my_table
WHERE role_id = 15
于 2012-08-29T07:20:31.807 回答