2

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

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 查询来做我想做的事。

明确指出,与乔有相同朋友的名字列表。

4

1 回答 1

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 relationship

有重复

如果可能有重复项(例如在您的问题初稿中),事情会变得有点复杂:

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')
于 2013-03-09T02:45:12.980 回答