可以写这个查询吗——我错过了什么?
Can this query be written - what am I missing?
我今天感觉很蠢,但我想写一个查询,但我感觉它可能超出我的能力范围。
为了简单起见,我会尽量简化问题。
我有一个table这样的
[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
我需要获取共享相同 class 的所有人的所有记录(未分组的实际记录),但有以下限制:
只给我 Jen、Jack 和 John 共享相同 class 的记录(只有这 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 包含在原始查询中,但我更喜欢这种方式以提高可读性。
不确定这是否是准确的答案,但我正在寻找的查询使用这种风格工作,我尝试使用相同的方法为像我一样卡住的任何人编写简单的答案。
如果你在 classes 之后你的三个人都共享相同的 class,即使有其他人参加,那么你的查询非常接近,除了你缺少 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
子句,这意味着您必须在外部查询中进行过滤。不过,希望您能看到我的查询与您的相似吗?
我今天感觉很蠢,但我想写一个查询,但我感觉它可能超出我的能力范围。
为了简单起见,我会尽量简化问题。
我有一个table这样的
[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
我需要获取共享相同 class 的所有人的所有记录(未分组的实际记录),但有以下限制:
只给我 Jen、Jack 和 John 共享相同 class 的记录(只有这 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 包含在原始查询中,但我更喜欢这种方式以提高可读性。
不确定这是否是准确的答案,但我正在寻找的查询使用这种风格工作,我尝试使用相同的方法为像我一样卡住的任何人编写简单的答案。
如果你在 classes 之后你的三个人都共享相同的 class,即使有其他人参加,那么你的查询非常接近,除了你缺少 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
子句,这意味着您必须在外部查询中进行过滤。不过,希望您能看到我的查询与您的相似吗?