Формат объединения SQL - вложенные внутренние соединения
У меня есть следующая инструкция SQL в старой системе, которую я рефакторинг. Это сокращенное представление для целей этого вопроса, просто показывая count (*).
SELECT COUNT(*)
FROM Table1
INNER JOIN Table2
INNER JOIN Table3 ON Table2.Key = Table3.Key AND Table2.Key2 = Table3.Key2
ON Table1.DifferentKey = Table3.DifferentKey
Он генерирует очень большое количество записей и убивает систему, но кто-то может объяснить синтаксис? И может ли это быть выражено любым другим способом?
- Таблица 1 содержит 419 строк
- Таблица 2 содержит 3374 строки
- Таблица 3 содержит 28182 строки
EDIT:
Предлагаемый переформатировать
SELECT COUNT(*)
FROM Table1
INNER JOIN Table3
ON Table1.DifferentKey = Table3.DifferentKey
INNER JOIN Table2
ON Table2.Key = Table3.Key AND Table2.Key2 = Table3.Key2
Ответы
Ответ 1
Для удобства чтения я изменил запрос... начиная с кажущегося верхнего уровня, который является Table1, который затем привязывается к Table3, а затем table3 привязывается к таблице2. Намного легче следовать, если вы следуете цепочке отношений.
Теперь, чтобы ответить на ваш вопрос. Вы получаете большое количество в результате декартова произведения. Для каждой записи в таблице 1, которая соответствует таблице 3, вы будете иметь X * Y. Тогда для каждого совпадения между таблицей 3 и таблицей 2 будет иметь такое же влияние... Y * Z... Итак, ваш результат только для одного возможного идентификатора в таблице 1 может иметь записи X * Y * Z.
Это основано на том, что вы не знаете, как нормализация или содержимое для ваших таблиц... если ключ является PRIMARY ключом или нет.
Ex:
Table 1
DiffKey Other Val
1 X
1 Y
1 Z
Table 3
DiffKey Key Key2 Tbl3 Other
1 2 6 V
1 2 6 X
1 2 6 Y
1 2 6 Z
Table 2
Key Key2 Other Val
2 6 a
2 6 b
2 6 c
2 6 d
2 6 e
Итак, таблица 1, присоединяющаяся к Таблице 3, приведет (в этом случае) к 12 записям (каждый из 1 присоединился к каждому из 3). Затем все, что снова умножается на каждую согласованную запись в таблице 2 (5 записей)... будет возвращено итоговое значение 60 (3 tbl1 * 4 tbl3 * 5 tbl2).
Итак, теперь, возьмите это и разверните на основе ваших 1000 записей, и вы увидите, как испорченная структура может задушить корову (так сказать) и убить производительность.
SELECT
COUNT(*)
FROM
Table1
INNER JOIN Table3
ON Table1.DifferentKey = Table3.DifferentKey
INNER JOIN Table2
ON Table3.Key =Table2.Key
AND Table3.Key2 = Table2.Key2
Ответ 2
Поскольку вы уже получили помощь по запросу, я возьму твой вопрос по вашему синтаксическому вопросу:
В первом запросе используется несколько менее известный синтаксис ANSI SQL, который позволяет вам встраивать соединения между предложениями join
и on
. Это позволяет вам объединить/объединить ваши соединения и, вероятно, открыть множество других злых, загадочных вещей.
Теперь, когда вложенное соединение не может ссылаться на более высокое значение в иерархии соединений, чем его непосредственный родитель, к нему присоединяются соединения над ним или вне его ветки... что именно делает этот уродливый маленький парень:
select
count(*)
from Table1 as t1
join Table2 as t2
join Table3 as t3
on t2.Key = t3.Key -- join #1
and t2.Key2 = t3.Key2
on t1.DifferentKey = t3.DifferentKey -- join #2
Это выглядит немного запутанным, потому что join # 2 соединяет t1-t2 без специфического ссылки на t2... однако он ссылается на t2 косвенно через t3 -as t3, соединен с t2 в соединении # 1. Хотя это может сработать, вы можете найти следующее немного (визуально) линейным и привлекательным:
select
count(*)
from Table1 as t1
join Table3 as t3
join Table2 as t2
on t2.Key = t3.Key -- join #1
and t2.Key2 = t3.Key2
on t1.DifferentKey = t3.DifferentKey -- join #2
Лично я обнаружил, что вложенность таким образом сохраняет мои утверждения в порядке, выделяя каждый уровень иерархии отношений. В качестве дополнительной заметки вам не нужно указывать внутреннюю. join неявно внутренне, если явно не указано иначе.