如何比较具有多个联合的表并加入?

How to compare tables with many unions and join?

我正在尝试查找仅在一个 table 中出现的行。大 table 名称(包含所有行)是 kwf_uploads,小 table 出现在许多名称中。我的目标是找到存在于 kwf_uploads 中但不存在于其他行中的行(此示例是 table 中没有关系的主键和外键)。

我在 sql 中做了什么:

select id from
kwf_uploads
left join

(SELECT picture_id as id
FROM documents where picture_id is not null
UNION 
SELECT file_id as id
FROM books where file_id is not null
UNION 
SELECT picture_id as id
FROM employee where picture_id is not null
UNION 
SELECT file_id as id
FROM flightFiles where file_id is not null
UNION 
SELECT picture_id as id
FROM tasks where picture_id is not null
UNION 
SELECT picture_id as id
FROM trainingContentQuestions where picture_id is not null
UNION 
SELECT picture_id as id
FROM trainingQuestions where picture_id is not null) foo  

ON kwf_uploads.id = foo.id

找到它:SQL: cascade UNION and JOIN

但失败并出现错误:SQL (1052): Column "id" in field list is ambiguous

我不想对每个 table 使用连接,因为我不擅长连接并且 sql 变得非常大且不可读。我也试过 not exists contrustion 没有任何结果。 我想我们可以找到更好的解决方案 =)

select id from kwf_uploads 查询的结果(9690 行):

联合查询的结果(6096 行):

结果我想看到 3594(9690 减去 6096)行。

修复您当前的错误

具有正确结果集别名的前缀 ID 列。在这种情况下 kwf_uploads.id。因为 Id 存在于两个结果集中。

得到想要的输出

添加Where foo.id is null。这将获取那些加入失败的 ID,这些是您想要的 ID。

  select kwf_uploads.id from
        kwf_uploads
        left join

        (SELECT picture_id as id
        FROM documents where picture_id is not null
        UNION 
        SELECT file_id as id
        FROM books where file_id is not null
        UNION 
        SELECT picture_id as id
        FROM employee where picture_id is not null
        UNION 
        SELECT file_id as id
        FROM flightFiles where file_id is not null
        UNION 
        SELECT picture_id as id
        FROM tasks where picture_id is not null
        UNION 
        SELECT picture_id as id
        FROM trainingContentQuestions where picture_id is not null
        UNION 
        SELECT picture_id as id
        FROM trainingQuestions where picture_id is not null) foo  

        ON kwf_uploads.id = foo.id
        where foo.id is null

在 DarkKnight 旁边回答:

您不需要在每个 union select 上包含 where。最坏的情况是你从所有 UNION 中得到一个 NULL 但它不会出现在 LEFT JOIN

select kwf_uploads.id 
from kwf_uploads
left join
    (
    SELECT picture_id as id FROM documents
    UNION 
    SELECT file_id as id FROM books
    UNION 
    SELECT picture_id as id FROM employee
    UNION 
    SELECT file_id as id FROM flightFiles
    UNION 
    SELECT picture_id as id FROM tasks
    UNION 
    SELECT picture_id as id FROM trainingContentQuestions 
    UNION 
    SELECT picture_id as id FROM trainingQuestions
    ) foo      
ON kwf_uploads.id = foo.id
where foo.id is null

UNION(单独使用时,没有 ALL)是一个 "expensive" 操作。

有一个替代方案,不存在。这个构造是 "semi join",我怀疑它可能比联合方法更便宜。

SELECT
      id
FROM kwf_uploads AS u
WHERE NOT EXISTS     (SELECT NULL FROM documents WHERE u.id = picture_id )
      AND NOT EXISTS (SELECT NULL FROM books WHERE u.id = file_id )
      AND NOT EXISTS (SELECT NULL FROM employee WHERE u.id = picture_id )
      AND NOT EXISTS (SELECT NULL FROM flightFiles WHERE u.id = file_id )
      AND NOT EXISTS (SELECT NULL FROM tasks WHERE u.id = picture_id )
      AND NOT EXISTS (SELECT NULL FROM trainingContentQuestions WHERE u.id = picture_id )
      AND NOT EXISTS (SELECT NULL FROM trainingQuestions WHERE u.id = picture_id )