INNER JOIN vs IN

时间:2011-01-21 05:12:00

标签: sql performance tsql syntax

SELECT C.* FROM StockToCategory STC 
INNER JOIN Category C ON STC.CategoryID = C.CategoryID 
WHERE STC.StockID = @StockID

VS

SELECT * FROM Category
WHERE CategoryID IN
    (SELECT CategoryID FROM StockToCategory WHERE StockID = @StockID)

哪个被认为是正确的(语法上)和最高效的方法以及为什么?

后一个例子中的语法对我来说似乎更合乎逻辑,但我的假设是JOIN会更快。

我查看了查询计划,但未能从中解析任何内容。

Query Plan 1
Query Plan 2

4 个答案:

答案 0 :(得分:10)

这两种语法有不同的用途。使用Join语法假定您需要StockToCategory和Category表中的某些内容。如果每个类别的StockToCategory表中有多个条目,则将重复“类别”表值。

使用IN功能假定您只需要ID符合某些条件的类别中的项目。如果给定的CategoryId(假设它是Category表的PK)在StockToCategory表中多次存在,则只返回一次。

在您的确切示例中,它们将生成相同的输出,但IMO,后面的语法使您的意图(只想要类别),更清晰。

顺便说一句,还有第三种语法类似于使用IN函数:

Select ...
From Category
Where Exists    (
                Select 1
                From StockToCategory
                Where StockToCategory.CategoryId = Category.CategoryId
                    And StockToCategory.Stock = @StockId
                )

答案 1 :(得分:1)

语法上(语义上)这些都是正确的。在性能方面,它们实际上是等效的,实际上我希望SQL Server为这两个查询生成完全相同的物理计划。

答案 2 :(得分:0)

认为只有两种方法可以指定相同的预期结果。

答案 3 :(得分:0)

for sqlite

table device_group_folders包含10条记录

table device_groups包含~100000条记录

INNER JOIN:31 ms

WITH RECURSIVE select_childs(uuid) AS (
SELECT uuid FROM device_group_folders WHERE uuid = '000B:653D1D5D:00000003'
UNION ALL
SELECT device_group_folders.uuid FROM device_group_folders INNER JOIN select_childs ON parent = select_childs.uuid
) SELECT device_groups.uuid FROM select_childs INNER JOIN device_groups ON device_groups.parent = select_childs.uuid;

在哪里31毫秒

WITH RECURSIVE select_childs(uuid) AS (
    SELECT uuid FROM device_group_folders WHERE uuid = '000B:653D1D5D:00000003'
UNION ALL
SELECT device_group_folders.uuid FROM device_group_folders INNER JOIN select_childs ON parent = select_childs.uuid
) SELECT device_groups.uuid FROM select_childs, device_groups WHERE device_groups.parent = select_childs.uuid;

IN< 1 ms

SELECT device_groups.uuid FROM device_groups WHERE device_groups.parent IN (WITH RECURSIVE select_childs(uuid) AS (
    SELECT uuid FROM device_group_folders WHERE uuid = '000B:653D1D5D:00000003'
    UNION ALL
    SELECT device_group_folders.uuid FROM device_group_folders INNER JOIN select_childs ON parent = select_childs.uuid
) SELECT * FROM select_childs);