在一个MySQL表中查找对集

时间:2015-09-07 02:05:40

标签: mysql sql database

假设有一张表T描述了拥有书籍的人。字段是pid(人员ID),bid(书籍ID):

-----------
|pid | bid|
-----------
| 1  |  1 | 
| 1  |  2 |
| 2  |  3 |
| 3  |  2 |
| 3  |  3 |
-----------

现在,我怎样才能找到所有没有共同书籍的人?在这个例子中,它应该返回(1,2)。

另外,如何确保不重复?例如,(1,2)和(2,1)是重复的。

1 个答案:

答案 0 :(得分:2)

让我们创建一个与

一起玩的表格
create table #temp1 (pid int, bid int)

insert into #temp1 (pid, bid) values (1,1)
insert into #temp1 (pid, bid) values (1,2)
insert into #temp1 (pid, bid) values (2,3)
insert into #temp1 (pid, bid) values (3,2)
insert into #temp1 (pid, bid) values (3,3)

步骤1.此查询查找共享书籍的所有人

select distinct t1.pid, t2.pid
FROM #temp1 t1 
inner join #temp1 t2 
on t1.bid = t2.bid AND t1.pid <> t2.pid

pid         pid
----------- -----------
1           3
2           3
3           1
3           2

步骤2.但问题是值是重复的。我们可以通过确保一个pid小于另一个pid来排除它们。

select distinct t1.pid, t2.pid
FROM #temp1 t1 
inner join #temp1 t2 
on t1.bid = t2.bid AND t1.pid <> t2.pid
where t1.pid < t2.pid

pid         pid
----------- -----------
1           3
2           3

现在问题是找到所有人并将他们从列表中排除,这些人有共同的书。

步骤3.我们可以获得所有人对

SELECT distinct t1.pid, t2.pid
FROM #temp1 t1, #temp1 t2
where t1.pid < t2.pid

pid         pid
----------- -----------
1           2
1           3
2           3

步骤4.我们需要使用步骤3中的结果并排除步骤2中的结果

SELECT STEP4.* FROM
(SELECT distinct t1.pid AS PID1, t2.pid AS PID2
 FROM #temp1 t1, #temp1 t2
 where t1.pid < t2.pid) STEP4
WHERE NOT EXISTS (SELECT * FROM
    (select distinct t1.pid AS PID1, t2.pid AS PID2
     FROM #temp1 t1 
     inner join #temp1 t2 
     on t1.bid = t2.bid AND t1.pid <> t2.pid
     where t1.pid < t2.pid) STEP2
  where STEP2.PID1 = STEP4.PID1 AND STEP2.PID2 = STEP4.PID2)

PID1        PID2
----------- -----------
1           2