INNER JOIN против IN - PullRequest
       2

INNER JOIN против IN

2 голосов
/ 21 января 2011
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 будет быстрее.

Я просмотрел планы запросов и не смог ничего расшифровать из них.

План запроса 1
План запроса 2

Ответы [ 4 ]

10 голосов
/ 21 января 2011

Два синтаксиса служат разным целям. Использование синтаксиса Join предполагает, что вы хотите что-то из таблиц StockToCategory и Category. Если в таблице StockToCategory имеется несколько записей для каждой категории, значения таблицы Category будут повторяться.

Использование функции IN предполагает, что вам нужны только элементы из категории, чей идентификатор соответствует некоторым критериям. Если заданный CategoryId (при условии, что это PK таблицы категорий) существует несколько раз в таблице StockToCategory, он будет возвращен только один раз.

В вашем конкретном примере они будут выдавать один и тот же вывод, однако IMO, более поздний синтаксис делает ваше намерение (только для категорий) более ясным.

Кстати, третий синтаксис, аналогичный использованию функции IN:

Select ...
From Category
Where Exists    (
                Select 1
                From StockToCategory
                Where StockToCategory.CategoryId = Category.CategoryId
                    And StockToCategory.Stock = @StockId
                )
1 голос
/ 21 января 2011

Синтаксически (семантически тоже) они оба верны. С точки зрения производительности они фактически эквивалентны, фактически я ожидал бы, что SQL Server будет генерировать одинаковые физические планы для этих двух запросов.

0 голосов
/ 22 июля 2017

за sqlite

таблица device_group_folders содержит 10 записей

таблица device_groups содержит ~ 100000 записей

ВНУТРЕННЕЕ СОЕДИНЕНИЕ: 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 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 мс </p>

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);
0 голосов
/ 21 января 2011

T думаю Есть только два способа указать один и тот же желаемый результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...