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

北城以北 提交于 2019-12-12 03:48:50

问题


For example, say you have a table of files and a logging table of transfer operations.

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)
)

A transfer operation can have various statuses -- 'succeeded', 'failed', 'in progress', etc. One file can have many transfer operations -- in particular, if a transfer fails, another transfer for that file may be scheduled later.

Now, say we want to find all the files with only failed transfers -- no transfers currently in progress, no later successful transfers.

So far I have the solution below with subselects:

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'
)

However, this feels a little clunky and procedural. Is there a more elegant solution, possibly involving self-joins?


回答1:


If you want to use self joins:

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



回答2:


How about an aggregation with a having clause?

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

If there is additional information from files that you want, you can join it in.




回答3:


I tend to use negated exists for these kinds of queries as they tend to perform fine with proper indices and in my opinion reflects the intent (or semantics) or the query well.

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
);


来源:https://stackoverflow.com/questions/32083618/select-records-in-table-a-with-only-certain-corresponding-records-in-table-b

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!