#sql #sql-server
#sql #sql-сервер
Вопрос:
Можно ли преобразовать приведенный ниже запрос в использование внутреннего соединения вместо подзапроса where В?
select i.*, it.*
from ItemTypes it
inner join Items i on (i.itemTypeID = it.ItemTypeID)
where i.itemID IN (......)
В подзапросе может быть возвращено 100 результатов, и я хочу избежать этого в подзапросе.
Комментарии:
1. вы пропустили подзапрос, как мы должны выяснить, можно ли его переписать с помощью join ?
2. Почему вы хотите избежать
IN
? В любом случае это полусоединение и, как правило, более эффективно в SQL Server, поскольку перезапись в качестве соединения может привести к дублированию.3. где i.ItemId IN (12313,123123,25234,1234345234,12342,123422,34,13435), но у меня может быть 100 или более идентификаторов в предложении IN.
4. @codecompleting — Ну и что? Если они возвращаются из подзапроса, это не имеет значения. Посмотрите на план выполнения, он будет реализован как полусоединение. Менее эффективно переписывать его, используя
JOIN
явно, чем использоватьDISTINCT
, чтобы избавиться от дубликатов.
Ответ №1:
Вы могли бы использовать выражение WITH common table (CTE):
;with SelectedItems (selectedIDs) as
(
select distinct itemID from [...] where [...]
)
select i.*, it.*
from ItemTypes it
inner join Items i on i.itemTypeID = it.ItemTypeID
inner join SelectedItems on selectedIDs = i.itemID
Вы также можете определить временную #таблицу с индексом для хранения выборок:
create table #SelectedItems
(
selItemID int primary key clustered
)
insert into #SelectedItems (selItemID)
select [...]
select i.*, it.*
from ItemTypes it
inner join Items i on i.itemTypeID = it.ItemTypeID
inner join #SelectedItems si on si.selItemID = i.itemID
drop table #SelectedItems
Но что бы вы ни делали, будьте осторожны при измерении производительности до и после любого изменения.
Комментарии:
1.
SelectedItems
Для представления вашего CTE также потребуетсяdistinct
ключевое слово, как указал @MartinSmith в моем ответе…
Ответ №2:
select i.*, it.*
from ItemTypes it
inner join Items i on (i.itemTypeID = it.ItemTypeID)
inner join (select itemID from Items where ...) i2 ON i.itemID = i2.itemID
Ответ №3:
Вы могли бы написать это так
select i.*, it.*
from ItemTypes it
inner join Items i on (i.itemTypeID = it.ItemTypeID)
inner join (select distinct itemID from [...] where [...]) i2
on (i.itemID = i2.itemID)
Но я сомневаюсь, что вы получите от этого выгоду. В конце концов, современные базы данных, как правило, находят оптимальный план выполнения для общих запросов и предложений. Однако в этом случае может потребоваться дополнительная работа, чтобы избавиться от дубликатов с помощью distinct
оператора
Комментарии:
1. Для этого необходимо
DISTINCT
будет поддерживать ту же семантику,IN
что и .2. Может быть, мне следует поместить свои идентификаторы в табличный тип, а затем присоединиться к нему?
3. @codecompleting: вы действительно измерили, что это медленно? Есть ли у вас соответствующие индексы для всех соответствующих столбцов?