Select table A 中的记录与 table B 中*仅*某些对应的记录

Select records in table A with *only* certain corresponding records in table B

例如,假设您有 table 个文件和 table 个传输操作记录。

CREATE TABLE files
(
  id INTEGER PRIMARY KEY
  -- various other columns
);

CREATE TABLE transfers
(
  id      INTEGER PRIMARY KEY,
  file_id INTEGER,
  status  TEXT NOT NULL,
  -- various other columns
  FOREIGN KEY (file_id) REFERENCES files (id)
)

一个传输操作可以有多种状态 -- 'succeeded''failed''in progress' 等。一个文件可以有多个传输操作 -- 特别是在传输失败的情况下,该文件的另一次传输可能会在稍后安排。

现在,假设我们要查找所有 只有 次传输失败的文件 -- 当前没有正在进行的传输,也没有以后成功的传输。

到目前为止,我有以下带有子选择的解决方案:

SELECT files.*
FROM files
WHERE files.id IN (
  SELECT DISTINCT file_id
  FROM transfers
  WHERE transfers.status == 'failed'
) AND files.id NOT IN (
  SELECT DISTINCT file_id
  FROM transfers
  WHERE transfers.status <> 'failed'
)

但是,这感觉有点笨拙和程序化。是否有更优雅的解决方案,可能涉及自连接?

带有 having 子句的聚合怎么样?

select t.file_id
from transfers t
group by t.file_id
having sum(case when status <> 'failed' then 1 else 0 end) = 0;

如果您需要来自 files 的其他信息,可以 join 加入。

如果您想使用自连接:

SELECT DISTINCT files.*
FROM
  files INNER JOIN transfers t1
  ON files.id = t1.file_id AND t1.status='failed'
  LEFT JOIN transfers t2
  ON file.id = t2.file_id AND t2.status<>'failed'
WHERE
  t2.id IS NULL

我倾向于对这些类型的查询使用否定 exists,因为它们往往在适当的索引下表现良好,并且在我看来很好地反映了意图(或语义)或查询。

SELECT file_id
FROM transfers t
WHERE t.status = 'failed'
  AND NOT EXISTS (
    SELECT 1 
    FROM transfers
    WHERE status <> 'failed'
      AND file_id = t.file_id
);