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会更快。
我查看了查询计划,但未能从中解析任何内容。
答案 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);