例如,假设您有一个文件表和一个传输操作的记录表。
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'
)
然而,这感觉有点笨拙和程序性。是否有更优雅的解决方案,可能涉及自连接?
答案 0 :(得分:3)
如果您想使用自我加入:
fillOne()
答案 1 :(得分:2)
带有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
进入。
答案 2 :(得分:1)
我倾向于对这些类型的查询使用否定的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
);