Понимание, как СОЕДИНЕНИЕ работает, когда 3 или больше таблицы включены. [SQL]

Другие довольно подробно объяснили вопрос, я хотел бы добавить примечание, что это неопределенное поведение в соответствии со стандартом.

C ++ 11 3.6.1 / 3 Основная функция

Функция main не должна использоваться в программе. Связь (3.5) с main определяется реализацией. Программа, которая определяет main как удаленный или объявляет main как встроенный, статический или constexpr, неверна. Имя main не является зарезервированным. [Пример: функции-члены, классы и перечисления могут называться main, как и сущности в других пространствах имен. - конец примера]

68
задан Ugo 14 November 2019 в 13:53
поделиться

4 ответа

Концептуально вот что происходит, когда вы объединяете три таблицы вместе.

  1. Оптимизатор предлагает план, который включает порядок объединения. Это может быть A, B, C или C, B, A или любая из комбинаций
  2. Механизм выполнения запросов применяет любые предикаты (предложение WHERE ) к первой таблице, которая не включает никаких других таблиц. Он выбирает столбцы, упомянутые в условиях JOIN , списке SELECT или списке ORDER BY . Назовите этот результат A
  3. . Он присоединяет этот набор результатов ко второй таблице. Для каждой строки он присоединяется ко второй таблице, применяя любые предикаты, которые могут применяться ко второй таблице. Это приводит к другому временному набору результатов.
  4. Затем он присоединяется к итоговой таблице и применяет ORDER BY

Это происходит концептуально. Фактически, на этом пути есть много возможных оптимизаций. Преимущество реляционной модели состоит в том, что надежная математическая основа делает возможными различные преобразования плана, не изменяя при этом его правильность.

Например, действительно нет необходимости генерировать полные наборы результатов в процессе. Вместо этого ORDER BY может выполняться путем доступа к данным, в первую очередь, с использованием индекса. Также можно выполнить множество типов соединений.

на самом деле нет необходимости генерировать полные наборы результатов по пути. Вместо этого ORDER BY может выполняться путем доступа к данным, в первую очередь, с использованием индекса. Также можно выполнить множество типов соединений.

на самом деле нет необходимости генерировать полные наборы результатов по пути. Вместо этого ORDER BY может выполняться путем доступа к данным, в первую очередь, с использованием индекса. Также можно выполнить множество типов соединений.

42
ответ дан 24 November 2019 в 14:23
поделиться

Мы знаем, что данные из B будут отфильтрованы (внутренним) соединением с A (данные в A также фильтруются). Итак, если мы (внутреннее) присоединяемся от B к C , то набор C будет также , отфильтрованным отношением к A . Также обратите внимание, что любые дубликаты из соединения будут включены .

Однако; в каком порядке это происходит, зависит от оптимизатора; он может решить сначала выполнить соединение B / C , затем ввести A или любую другую последовательность (возможно, на основе предполагаемого количества строк из каждого соединения и соответствующие индексы).


ОДНАКО; в вашем более позднем примере вы используете соединение LEFT OUTER ; поэтому Аккаунт не фильтруется вообще , и вполне может быть дублирован, если какая-либо из других таблиц имеет несколько совпадений.

Есть ли дубликаты (для каждой учетной записи) в BalanceToken ?

5
ответ дан 24 November 2019 в 14:23
поделиться

Я часто считаю, что помогает просмотреть фактический план выполнения. В Query Analyzer / Management Studio вы можете включить это для запросов из меню Query или использовать Ctrl + M. После выполнения запроса план, который был выполнен, отображается на другой вкладке результатов. Из этого вы увидите, что сначала соединяются C и B, а затем результат соединяется с A. План может варьироваться в зависимости от информации, имеющейся в СУБД, потому что оба соединения являются внутренними, что делает его A-and-B-and-C . Я имею в виду, что результат будет одним и тем же независимо от того, какое соединение будет выполнено первым, но время, необходимое для этого, может сильно отличаться, и именно здесь в игру вступают оптимизатор и подсказки.

1
ответ дан 24 November 2019 в 14:23
поделиться

Соединения могут быть непростыми, и большая часть поведения, конечно, продиктована тем, как данные хранятся в реальных таблицах.

Не видя таблиц, трудно дать четкий ответ в ваш конкретный случай, но я думаю, что основная проблема заключается в том, что вы суммируете несколько наборов результатов, которые объединяются в один.

Возможно, вместо нескольких объединений вы должны создать в своем запросе две отдельные временные таблицы, одну с идентификатором учетной записи, датой и суммой начальных балансов, вторую с идентификатором учетной записи, датой и суммой конечных балансов, а затем объединить эти две таблицы по идентификатору учетной записи. и дату.

Чтобы точно узнать, что происходит с объединениями, в том числе и в вашем конкретном случае, я бы сделал следующее:

Изменил начальную часть

SELECT accountID Accountbalancedate, sum (...) как начальный баланс, sum (...) как закрывающий баланс FROM

до простого

«SELECT * FROM»

Изучите полученную таблицу, и вы увидите, какие именно данные дублируются. Удалите объединения одно за другим и посмотрите, что произойдет. Это должно дать вам представление о том, что именно в ваших данных вызывает дублирование.

Если вы открываете запрос в SQL Server Management Studio (существует бесплатная версия), вы можете редактировать запрос в дизайнере. Визуальное представление того, как соединяются таблицы, также может помочь вам понять, что происходит.

1
ответ дан 24 November 2019 в 14:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: