我正在寻找一种有效的方法来查询具有相同值集的项目。
我有一张下表
C_1 C_2
--------
A 1
A 2
-------
B 1
B 2
B 3
-------
C 1
C 2
-------
D 1
D 2
D 3
-------
E 1
E 2
-------
F 0
F 2
我将选择FROM C_1中与给定项目具有完全相同的c_2元素集的项目列表。
对于项目A,我将
C
E
对于项目B,我将
D
如何在SQL(Oracle 10g)中完成?
以下是用于测试目的的create table语句
create table t (c_1 varchar2(1), c_2 number);
INSERT into t VALUES('A', 1);
INSERT into t VALUES('A', 2);
INSERT into t VALUES('B', 1);
INSERT into t VALUES('B', 2);
INSERT into t VALUES('B', 3);
INSERT into t VALUES('C', 1);
INSERT into t VALUES('C', 2);
INSERT into t VALUES('D', 1);
INSERT into t VALUES('D', 2);
INSERT into t VALUES('D', 3);
INSERT into t VALUES('E', 1);
INSERT into t VALUES('E', 2);
INSERT into t VALUES('F', 0);
INSERT into t VALUES('F', 2);
答案 0 :(得分:3)
create type t_c_2 as table of number;
select one.c_1, two.c_1
from (select t.c_1, CAST(COLLECT(t.c_2) as t_c_2) coll
from t
group by t.c_1) one
,(select t.c_1, CAST(COLLECT(t.c_2) as t_c_2) coll
from t
group by t.c_1) two
where one.coll = two.coll
and one.c_1 != two.c_1;
我从未在生产现场使用过这样的结构,需要进行效率验证。
答案 1 :(得分:3)
您可以使用10g的COLLECT
功能;因为您不想查看c_2值是什么,所以您甚至不需要cast
它。
select c_1
from t
where c_1 != 'A'
group by c_1
having collect(c_2) = (select collect(c_2) from t where c_1 = 'A' group by c_1)
/
答案 2 :(得分:2)
您需要的是一个部门:
http://en.wikipedia.org/wiki/Relational_algebra#Division_.28.C3.B7.29
或类似的问题:
不幸的是,使用SQL表示分割并不像关系代数那样容易。
答案 3 :(得分:1)
SELECT
[search].c_1,
[match].c_1
FROM
t AS [search]
INNER JOIN
t AS [match]
ON [search].c_2 = [match].c_2
GROUP BY
[search].c_1,
[match].c_1
HAVING
COUNT(*) = (SELECT COUNT(*) FROM t WHERE c_1 = [search].c_1)
AND COUNT(*) = (SELECT COUNT(*) FROM t WHERE c_1 = [match].c_1)
为获得最佳性能,您需要两个索引。一个在c_1
上,另一个在c_2
上
- c_1
上的索引使两个SELECT COUNT(*)
查询进行简单的索引查找
- c_2
上的索引使联接成为查找。
您可以添加AND [search].c_1 != [match].c_1
来停止与自身匹配的设置。
答案 4 :(得分:0)
类似的东西:
SELECT DISTINCT c_1
FROM (SELECT c_1, c_2, COUNT(*) over(PARTITION BY c_1) cnt FROM t)
WHERE (SELECT MAX(c_2) FROM t WHERE c_1 = 'A') = cnt
AND c_1 <> 'A'
不确定性能,你可以试着稍微说一下,告诉我它是否有效