sql-server - SQL 效率 : WHERE IN Subquery vs. JOIN then GROUP

标签 sql-server performance tsql

举个例子,我想获取应用了某些标签的所有项目的列表。我可以执行以下任一操作:

SELECT Item.ID, Item.Name
FROM Item
WHERE Item.ID IN (
    SELECT ItemTag.ItemID
    FROM ItemTag
    WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55)

或者

SELECT Item.ID, Item.Name
FROM Item
LEFT JOIN ItemTag ON ItemTag.ItemID = Item.ID
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55
GROUP BY Item.ID, Item.Name

或者完全不同的东西。

一般来说(假设有一般规则),什么是更有效的方法?

最佳答案

SELECT Item.ID, Item.Name
FROM Item
WHERE Item.ID IN (
    SELECT ItemTag.ItemID
    FROM ItemTag
    WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55)

or

SELECT Item.ID, Item.Name
FROM Item
LEFT JOIN ItemTag ON ItemTag.ItemID = Item.ID
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55
GROUP BY Item.ID

您的第二个查询将无法编译,因为它引用 Item.Name 且未对其进行分组或聚合。

如果我们从查询中删除GROUP BY:

SELECT  Item.ID, Item.Name
FROM    Item
JOIN    ItemTag
ON      ItemTag.ItemID = Item.ID
WHERE   ItemTag.TagID = 57 OR ItemTag.TagID = 55

这些仍然是不同的查询,除非 ItemTag.ItemIdUNIQUE 键并如此标记。

SQL Server 能够检测 UNIQUE 列上的 IN 条件,并且只会转换 IN > 条件转换为 JOIN

如果ItemTag.ItemID不是UNIQUE,则第一个查询将使用一种SEMI JOIN算法,该算法在以下方面非常有效SQL Server

您可以将第二个查询转换为JOIN:

SELECT  Item.ID, Item.Name
FROM    Item
JOIN    (
        SELECT DISTINCT ItemID
        FROMT  ItemTag
        WHERE  ItemTag.TagID = 57 OR ItemTag.TagID = 55
        ) tags
ON      tags.ItemID = Item.ID

但是这个比 INEXISTS 效率稍低。

请参阅我博客中的这篇文章,了解更详细的性能比较:

关于sql-server - SQL 效率 : WHERE IN Subquery vs. JOIN then GROUP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1179231/

相关文章:

sql - Sql Server 中的单元格比较?

sql-server - SQL Server 连接字符串问题

sql-server - TADOStoredProc 和 SQL Server 存储过程,参数作为默认值

sql-server - 消息 8120 : Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

sql-server - t-sql udf,获取参数的数据类型

tsql - 需要一些 tSQL 巫术 : SQL Update Based on Running Total

sql - 跨不同数据库查询 - 同一表 SQL Server 2012

php - 打开/关闭标签和性能?

c++ - 为什么 strcmp 比我的函数快这么多?

c# - 在 "out"参数中传递值类型是否会导致变量被装箱?