如何查询具有相同值集的项目

时间:2011-06-15 09:56:02

标签: sql oracle oracle10g

我正在寻找一种有效的方法来查询具有相同值集的项目。

我有一张下表

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);

5 个答案:

答案 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

或类似的问题:

Is there set division in SQL?

不幸的是,使用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'

不确定性能,你可以试着稍微说一下,告诉我它是否有效