可以写这个查询 - 我错过了什么?

时间:2016-12-12 16:01:00

标签: oracle oracle12c

我今天感觉很愚蠢,但我有一个我想写的查询,但我感觉它可能超出了我的范围。

为了简单起见,我会尝试简化问题。

我有一张这样的表

[Table A]
ID | Class | Name
0      A     Sarah
1      B     Tom
2      C     Bob
3      A     Jen
4      A     John
5      A     Jack
6      B     Name1
7      B     Jack
8      B     Bob

我需要为所有共享同一类的人获取所有记录(实际记录未分组),但有以下限制:

只有Jen,Jack&约翰共享同一个班级(只有那3个没有其他人,没有重复)。

这意味着记录将以3的集合形式出现。

所以在上面的例子中我会得到

3      A     Jen
4      A     John
5      A     Jack

到目前为止,我已经得到了:

SELECT Class, Name, COUNT(*)
FROM TableA
GROUP BY Class, Name
HAVING COUNT(*) = 3

但除了这种方法不正常之外,我无法指定记录必须包含Jen,Jack和John这两个名称。

编辑: 我能够使用内部查询来做到这一点,但它有点慢..如果有人知道更优化的方式,请告诉我:

SELECT ....
FROM TableA t1
join TableA  t2 on t1.class = t2.class
WHERE t1.name = 'Jen' AND t2.name = 'John'
AND t1.class IN(SELECT class FROM TableA t3 WHERE t3.name = 'Jack'))) 

我可能已将t3包含在原始查询中,但我更喜欢这种方式以便于阅读。

不确定这是否是确切的答案,但我正在寻找的查询使用这种风格,我尝试使用相同的方法编写简单的方法,对于像我一样卡住的人。

1 个答案:

答案 0 :(得分:2)

如果您在三个人共享同一课程的课程之后,即使有其他人参加,那么您的查询非常接近,除非您错过WHERE子句将行限制为您感兴趣的名称。

另外,看到你没有想要折叠行("the actual records, not grouped by"),那么你就是在分析COUNT之后,而不是聚合。

因此,您之后会看起来像:

WITH table_a AS (SELECT 0 ID, 'A' CLASS, 'Sarah' NAME FROM dual UNION ALL
                 SELECT 1 ID, 'B' CLASS, 'Tom' NAME FROM dual UNION ALL
                 SELECT 2 ID, 'C' CLASS, 'Bob' NAME FROM dual UNION ALL
                 SELECT 3 ID, 'A' CLASS, 'Jen' NAME FROM dual UNION ALL
                 SELECT 4 ID, 'A' CLASS, 'John' NAME FROM dual UNION ALL
                 SELECT 5 ID, 'A' CLASS, 'Jack' NAME FROM dual UNION ALL
                 SELECT 6 ID, 'B' CLASS, 'Name1' NAME FROM dual UNION ALL
                 SELECT 7 ID, 'B' CLASS, 'Jack' NAME FROM dual UNION ALL
                 SELECT 8 ID, 'B' CLASS, 'Bob' NAME FROM dual)
-- End of mimicking your table_a with data in it
-- See query below:
SELECT ID,
       CLASS,
       NAME
FROM   (SELECT ID,
               CLASS,
               NAME,
               COUNT(NAME) OVER (PARTITION BY CLASS) name_cnt
        FROM   table_a
        WHERE  NAME IN ('Jen', 'Jack', 'John'))
WHERE  name_cnt = 3;

您会注意到,分析函数没有聚合函数所具有的等效HAVING子句,这意味着您必须在外部查询中进行过滤。希望你能看到我的查询与你的查询相似吗?