ОТЛИЧАЙТЕСЬ с РАЗДЕЛЕНИЕМ по сравнению с GROUPBY

Я нашел некоторые SQL-запросы в приложении, которое я рассматриваю следующим образом:

SELECT DISTINCT
Company, Warehouse, Item,
SUM(quantity) OVER (PARTITION BY Company, Warehouse, Item) AS stock

Я уверен, что это дает тот же результат, что и:

SELECT
Company, Warehouse, Item,
SUM(quantity) AS stock
GROUP BY Company, Warehouse, Item

Есть ли какая-либо польза (производительность, читаемость, дополнительная гибкость при написании запроса, ремонтопригодность и т.д.) с использованием первого подхода к более позднему?

Ответ 1

Производительность:

Победитель: GROUP BY

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

План запроса GROUP BY включал только операцию сканирования и агрегирования таблицы, тогда как план PARTITION BY имел два вложенных цикла. PARTITION BY занял около 2800 мс во втором прогоне, GROUP BY заняло всего 500 мс.

Считываемость/ремонтопригодность:

Победитель: GROUP BY

Основываясь на мнениях комментаторов здесь, PARTITION BY менее читабельен для большинства разработчиков, поэтому его, вероятно, будет еще труднее поддерживать в будущем.

Гибкость

Победитель: PARTITION BY

PARTITION BY дает вам большую гибкость при выборе столбцов группировки. С GROUP BY вы можете иметь только один набор столбцов группировки для всех агрегированных столбцов. С помощью DISTINCT + PARTITION BY в каждом разделе может быть разный столбец. Также на некоторых СУБД вы можете выбрать из более агрегированных/аналитических функций в предложении OVER.

Ответ 2

Использование sum() в качестве аналитической функции с over partition by не требуется. Я не думаю, что есть большая разница между ними в любом смысле. В оракуле гораздо больше аналитической функции, чем функция агрегации. Я думаю, что ms-sql - это тот же случай. И, например, lag(), lead(), rank(), dense rank() и т.д. Гораздо сложнее реализовать только с group by. Конечно, этот аргумент не предназначен для защиты первой версии...

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

Ответ 3

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

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

Второй возвращает только одну строку для каждой комбинации компаний/складов/товаров.

Итак, да, в этом примере первый запрос кажется немного бесполезным... если вы не хотите вычислять статистику уровня запаса, например текущее соотношение акций по сравнению с общим количеством компании/складом/товаром (просто пример, t знать, имеет ли он какое-либо деловое значение!)

Аналитическая функция - очень мощный механизм в SQL, в некотором смысле более мощный, чем групповой. Но используйте его с осторожностью... Простое эмпирическое правило может быть: если вы можете вычислить его с помощью группы, не используйте аналитическую функцию;)