获取仅连接到另一个表中某些类型的行的行

use*_*239 1 sql-server

我在一个人表中有行。每个都可以通过链接表链接到事物表中的多行。每个事物都有一个 objectType。我想获取 person 表中仅链接到三个特定 objectType 的所有行,并且每个人只需要一行。我是 SQL 新手,不知道从哪里开始。我已经设置了一个示例:

http://sqlfiddle.com/#!18/56bd69/2

仅使用 INNER JOINS 和 WHERE 不起作用,因为它返回所有人员行。

Len*_*art 5

未经测试(似乎是小提琴的一些技术问题),但您可能正在寻找 Exist 谓词

SELECT p.*
FROM person as p
WHERE EXISTS (
    SELECT 1
    FROM link as l
    JOIN thing as t
        ON t.objectID = l.thingObjectId
    WHERE t.objectType IN ('fork','knife','eraser')
      AND p.objectID = l.personObjectId
) ;
Run Code Online (Sandbox Code Playgroud)

编辑:根据评论中的信息,很明显你想要拥有所有 3 种对象类型的人(我假设有)。在 SQL 中没有 ALL 量词(与 EXISTS 相反)。但是,可以进行转换:

ALL x:p(x) <=> NOT EXISTS x:NOT x 
Run Code Online (Sandbox Code Playgroud)

正如您在评论中指出的那样,这将导致:

SELECT p.*
FROM person as p
WHERE NOT EXISTS (
    SELECT 1
    FROM link as l
    JOIN thing as t
        ON t.objectID = l.thingObjectId
    WHERE t.objectType NOT IN ('fork','knife','eraser')
      AND p.objectID = l.personObjectId
) ;
Run Code Online (Sandbox Code Playgroud)

另一种选择是计算在 3 个对象中哪些人恰好拥有 3 个对象:

 SELECT p.rowkey
 FROM person as p
 JOIN link as l
     ON p.objectId = l.personObjectId
 JOIN thing as t
     ON t.objectID = l.thingObjectId
 WHERE t.objectType IN ('fork','knife','eraser')
 GROUP BY p.rowkey
 HAVING COUNT( DISTINCT t.objectType ) = 3;
Run Code Online (Sandbox Code Playgroud)

这是我所知道的两种最常用的关系划分技术。

  • 您的第一个 EXISTS 查询将选择也没有全部三个的行。 (2认同)