【问题标题】:select rows that do not have any foreign keys linked选择没有链接任何外键的行
【发布时间】:2009-05-26 03:53:50
【问题描述】:

我有 2 张桌子 群体和人

人们的 GroupId 链接到 Group.GroupId(主键)

如何选择没有人的群组?在 t-sql 和 linq 中

谢谢

【问题讨论】:

    标签: sql linq


    【解决方案1】:

    更新

    我已经通过 SQL Server 2005 运行了四种不同的方法来执行此操作,并包含执行计划。

    -- 269 reads, 16 CPU
    SELECT *
    FROM Groups
    WHERE NOT EXISTS (
        SELECT *
        FROM People
        WHERE People.GroupId = Groups.GroupId
    );
    
    -- 249 reads, 15 CPU
    SELECT *
    FROM Groups
    WHERE (
        SELECT COUNT(*)
        FROM People
        WHERE People.GroupId = Groups.GroupId
    ) = 0
    
    -- 249 reads, 14 CPU
    SELECT *
    FROM Groups
    WHERE GroupId NOT IN (
        SELECT DISTINCT GroupId
        FROM Users
    )
    
    -- 10 reads, 12 CPU
    SELECT *
    FROM Groups
        LEFT JOIN Users ON Users.GroupId = Groups.GroupId
    WHERE Users.GroupId IS NULL
    

    所以最后一个,虽然可以说是四个中可读性最低的,但表现最好。

    这让我感到惊讶,老实说,我仍然更喜欢 WHERE NOT EXISTS 语法,因为我认为它更明确 - 它读起来与您尝试做的完全一样。

    【讨论】:

    • SQL Server 的探查器。它告诉你每个查询花费了多少读取和 CPU 时间(我一个一个地运行它们)。
    【解决方案2】:

    我首选的方法是左反半连接:

    SELECT    g.*
    FROM      Groups g
    LEFT JOIN People p ON g.GroupID = p.GroupID
    WHERE     p.GroupID IS NULL
    

    我发现它最直观、最灵活、最高效。

    我写了一篇关于各种查询策略来搜索缺失数据的整篇文章 - 如果您有兴趣,请查看 here

    【讨论】:

    • 我不知道它是否比 WHERE NOT EXISTS 更直观,但仍然 +1。
    • +1,外连接和检查IS NULL 在mysql 中绝对是一种性能良好的方法(但不确定它在性能方面如何与各种SQL Server 版本中的WHERE NOT EXITS 进行比较)。
    • 如果方法的效率没有卖给我,'left-anti-semi join' 的文字锻造确实... ;)
    【解决方案3】:

    我认为最简单的解决方案是:

    SELECT * 
    FROM GROUPS
    WHERE GroupId NOT IN (SELECT DISTINCT GroupId FROM People)
    

    【讨论】:

    • 当 'People' 中的 'GroupId' 列允许为 Null 时,您应该将查询更改为:SELECT * FROM GROUPS WHERE GroupId NOT IN (SELECT DISTINCT GroupId FROM People WHERE GroupId IS NOT NULL)
    猜你喜欢
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    相关资源
    最近更新 更多