Формат объединения 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 неявно внутренне, если явно не указано иначе.