SQL中的返回字段在第二个字段上相交?

时间:2013-03-09 02:38:40

标签: sql db2 relational-division

我正在尝试返回具有特定人员相交字段的字段。我的意思是

Name    Friend
----    -----
Joe     Sally
Joe     Bill
Mary    Sally
Mary    Michael
Mike    Joe
Bill    Bill
Bill    Sally
Gil     Sally
Gil     Bill
Gil     David

说,我们想要与Joe的第二列匹配的人员列表,他们必须匹配Sally和Bill。所以只有比尔符合这个标准,因为玛丽有一个,但她没有比尔。吉尔有莎莉和比尔,但他也有大卫。所以只有比尔才能归还。我认为INTERSECT的某些内容会起作用,因为它会返回常见的字段,但我认为这并不能说明有更多的字段。不确定如何编写SQL查询来执行我想要的操作。

清楚地说明了与Joe拥有完全相同的朋友的名单。

1 个答案:

答案 0 :(得分:0)

没有重复

SELECT p2.name
FROM   people AS p1
JOIN   people AS p2 ON p2.number = p1.number
                   AND p2.name <> p1.name    -- exclude self-join
WHERE  p1.name = 'Joe'
AND NOT EXISTS (
   SELECT 1 
   FROM   people p3
   WHERE  p3.name = p2.name  
   AND    p3.number <> p1.number
   )
GROUP  BY p2.name
HAVING count(*) = (SELECT count(*) FROM people WHERE name = 'Joe')

只有当您想要排除那些其他朋友的人没有乔时,才需要AND NOT EXISTS ...的最后一个条件。
它会从结果中排除示例中的Gil

这是关系划分的特例(带有自引用表)。你可以在这个相关的答案中找到一整套查询技巧:
How to filter SQL results in a has-many-through relation

带有重复项

如果可能存在重复项(例如问题的第一稿),事情会变得复杂一些:

WITH p AS (
   SELECT name, number, count(*) AS ct
   FROM   people
   GROUP  BY name, number
   )
SELECT p2.name
FROM   p AS p1
JOIN   p AS p2 ON p2.number = p1.number
              AND p2.ct = p1.ct
              AND p2.name <> p1.name    -- exclude self-join
WHERE  p1.name = 'Joe'
AND NOT EXISTS (
   SELECT 1 
   FROM   p p3
   WHERE  p3.name = p2.name  
   AND    p3.number <> p1.number
   )
GROUP  BY p2.name
HAVING count(*) = (SELECT count(*) FROM p WHERE name = 'Joe')