【问题标题】:transform union query to join query将联合查询转换为连接查询
【发布时间】:2017-10-24 10:02:35
【问题描述】:

我有一个由 3 个表组成的简单数据库架构

用户
身份证
名称
矩阵

文档
身份证
连载
user_id(文档所有者:用户(id)的外键)

User_Document(连接表)
用户ID
document_id

我想要来自两个用户来源的所有文档序列:文档所有者和连接表。查询由用户矩阵列表过滤

我设法通过联合查询实现了预期目标:

select d.serial from Document d  
INNER JOIN  users u ON u.id = d.user_id 
where u.matricule IN ('1234')
UNION
select d.serial from Document d 
inner join User_Document ud on d.id = ud.document_id 
inner join users u on ud.user_id = u.id 
where u.matricule IN ('1234')

如何只用一个连接查询得到相同的结果?我还需要跳过没有序列号的文档(这种情况是可能的)

非常感谢

【问题讨论】:

    标签: sql join


    【解决方案1】:

    试试这个:

    SELECT d.serial
    FROM Document d 
        LEFT JOIN User_Document ud
            ON d.id = ud.document_id 
        LEFT JOIN users u
            on ud.user_id = u.id 
        LEFT JOIN users u2
            ON d.user_id = u2.id
    WHERE d.serial IS NOT NULL
    AND 
    (
        ISNULL(u.matricule,'') IN ('1234')
        OR ISNULL(u2.matricule,'') IN ('1234')
    )
    

    【讨论】:

    • 有趣。此查询可以返回重复项,就像现在编写的那样,而您的版本不会。
    【解决方案2】:

    为什么要删除joins?最有效的查询可能会使用exists

    select d.*
    from documents d
    where d.serial is not null and
          (exists (select 1
                   from users u
                   where u.id = d.user_id and u.matricule = '1234'
                  ) or
           exists (select 1
                   from user_document ud join
                        users u
                        on u.id = d.user_id 
                   where ud.document_id = d.id and u.matricule = '1234'
                  )
          );
    

    为此,您需要在users(id, matricule)user_documents(document_id, user_id)documents(serial, user_id, document_id) 上建立索引。

    使用索引可以消除重复项——这对于这种类型的查询来说应该是一个巨大的胜利。

    【讨论】:

    • 我不想删除 join 但 union 。你是对的,当表格增长时我需要一些索引。您的查询也很有效。非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    相关资源
    最近更新 更多