В КУРСЕ?

Разбираемся в теме

SQL-запрос выполнился, а сумма выросла: что соединение сделало со строками

Отсутствие ошибки SQL не означает, что запрос отвечает на поставленный вопрос. После соединения таблиц одна исходная строка может появиться несколько раз, и сумма изменится без появления новых заказов. Разберём это на двух вымышленных заказах и трёх товарных позициях. Такой небольшой пример удобно использовать в учебном симуляторе или проверить вручную на бумаге.

Сначала определить, что представляет одна строка

В таблице orders каждая строка описывает заказ: его идентификатор и общую сумму. В таблице items каждая строка описывает отдельную позицию заказа. Значит, две таблицы имеют разную детализацию. У одного заказа может быть несколько позиций. Соединение по идентификатору сопоставляет строки, удовлетворяющие условию, и сохраняет получившиеся пары. Оно не обязано сохранять исходное число заказов в виде такого же числа строк результата. Прежде чем складывать значения, полезно назвать сущность, которую представляет каждая строка после соединения.

Повторение можно увидеть без сложного запроса

Пусть заказ A имеет общую сумму сто, а заказ B двести. У A две позиции, у B одна. После внутреннего соединения заказов с позициями появятся три строки: A с первой позицией, A со второй и B с единственной. Общая сумма A повторится дважды. Поэтому сложение поля общей суммы в результате даст четыреста, хотя исходные заказы вместе составляют триста. Запрос может быть синтаксически правильным: ошибка заключается в выборе уровня данных для расчёта. База выполняет описанную операцию, а не угадывает бизнес-смысл вопроса.

Исправление зависит от нужного показателя

Если требуется сумма всех заказов без условий по позициям, её можно считать на уровне таблицы заказов. Если нужны сведения о позициях, следует отдельно продумать группировку или проверку существования подходящих строк. Простое удаление одинаковых денежных значений опасно: два разных заказа могут иметь одну и ту же сумму. Уникальность определяется идентификатором сущности, а не совпадением числа. Также важно учитывать заказы без позиций: внутреннее соединение исключит их из результата. Проверка маленького набора помогает заранее увидеть подобные крайние случаи.

Попробуйте на практике

Вручную смоделируйте соединение двух таблиц. Используйте только придуманные обозначения; подключение к рабочей базе и изменение данных не нужны.

  1. Запишите таблицу заказов: A со значением сто и B со значением двести. Укажите, что суммы относятся ко всему заказу, а не к отдельной позиции.
  2. Создайте таблицу позиций: две строки с идентификатором A и одну с B. Присвойте позициям разные условные номера.
  3. Выпишите все пары строк с совпадающим идентификатором заказа. Посчитайте строки результата и сумму повторившегося поля общей стоимости.
  4. Сравните результат с суммой исходных заказов. Объясните расхождение через детализацию и число совпадений, а не через ошибку арифметики.
  5. Измените сумму B на сто и подумайте, почему удаление одинаковых значений суммы теперь потеряет отдельный заказ. Сформулируйте требуемый уровень расчёта.

Как проверить результат. Первое соединение даёт три строки и ошибочную для суммы заказов величину четыреста вместо трёхсот. После изменения B два разных заказа имеют одинаковую сумму сто, поэтому совпадение денежных значений не делает их одной сущностью.

Частые вопросы

JOIN всегда увеличивает число строк?

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

Правильный результат на одном примере подтверждает весь запрос?

Он подтверждает только разобранный случай. Добавьте другие ситуации: несколько совпадений, отсутствие совпадений и одинаковые суммы у разных заказов. Ожидаемые результаты следует определить заранее, а не подгонять под вывод запроса.

Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.

Зарегистрируйтесь, чтобы уточнить возможность доступа к этому материалу

Зарегистрироваться
← К списку материалов