Сначала предположим, что (id)
это первичный ключ таблицы. В этом случае, да, объединения являются (могут быть доказаны) избыточными и могут быть исключены.
Теперь это просто теория - или математика. Для того, чтобы оптимизатор выполнил фактическое исключение, теория должна быть преобразована в код и добавлена в набор оптимизаторов / переписываний / исключений оптимизатора. Чтобы это произошло, разработчики (СУБД) должны подумать, что это будет иметь хорошие преимущества для эффективности и что это достаточно распространенный случай.
Лично это не похоже на один (достаточно распространенный). Запрос - как вы признаете - выглядит довольно глупо, и рецензент не должен позволять ему проходить проверку, если только он не был улучшен и избыточное соединение удалено.
Тем не менее, есть похожие запросы, где устранение происходит. Роб Фарли написал очень хороший пост в блоге: упрощение JOIN в SQL Server .
В нашем случае все, что нам нужно сделать, это изменить соединения на LEFT
объединения. Смотрите dbfiddle.uk . Оптимизатор в этом случае знает, что соединение может быть безопасно удалено без возможного изменения результатов. (Логика упрощения довольно общая и не предназначена для самостоятельных соединений.)
Конечно, в исходном запросе удаление INNER
объединений также не может изменить результаты. Но самоприсоединение по первичному ключу вообще не является обычным, поэтому в оптимизаторе этот случай не реализован. Однако обычно объединение (или левое соединение) выполняется, когда столбец объединения является первичным ключом одной из таблиц (и часто существует ограничение внешнего ключа). Что приводит ко второму варианту устранения объединений: добавьте (внешняя ссылка!) Ограничение внешнего ключа:
ALTER TABLE "Table"
ADD FOREIGN KEY (id) REFERENCES "Table" (id) ;
И вуаля, соединения устранены! (проверено в той же скрипке): здесь
create table docs
(id int identity primary key,
doc varchar(64)
) ;
GO
✓
insert
into docs (doc)
values ('Enter one batch per field, don''t use ''GO''')
, ('Fields grow as you type')
, ('Use the [+] buttons to add more')
, ('See examples below for advanced usage')
;
GO
4 ряда пострадали
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1
join docs d2 on d2.id=d1.id
join docs d3 on d3.id=d1.id
join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | доктор
-: | : ----------------------------------------
1 | Введите одну партию в поле, не используйте «GO»
2 | Поля растут по мере ввода
3 | Используйте кнопки [+], чтобы добавить больше
4 | Смотрите примеры ниже для расширенного использования
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1
left join docs d2 on d2.id=d1.id
left join docs d3 on d3.id=d1.id
left join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | доктор
-: | : ----------------------------------------
1 | Введите одну партию в поле, не используйте «GO»
2 | Поля растут по мере ввода
3 | Используйте кнопки [+], чтобы добавить больше
4 | Смотрите примеры ниже для расширенного использования
alter table docs
add foreign key (id) references docs (id) ;
GO
✓
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1
join docs d2 on d2.id=d1.id
join docs d3 on d3.id=d1.id
join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
id | доктор
-: | : ----------------------------------------
1 | Введите одну партию в поле, не используйте «GO»
2 | Поля растут по мере ввода
3 | Используйте кнопки [+], чтобы добавить больше
4 | Смотрите примеры ниже для расширенного использования