Нужно отобразить в таблице выборку из таблицы, а в последней строке указать аггрегацию по некоторым полям. Запрос выполняется из ruby, поэтому многопоточность и async/await недоступны. Первая мысль — запихнуть всё в один запрос вида
SELECT a, b, c FROM table UNION SELECT null, avg(b), max(c) FROM table
Насколько это идиоматично?
Re: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, cppguard, Вы писали:
C>Нужно отобразить в таблице выборку из таблицы, а в последней строке указать аггрегацию по некоторым полям. Запрос выполняется из ruby, поэтому многопоточность и async/await недоступны. Первая мысль — запихнуть всё в один запрос вида C>
C>SELECT a, b, c FROM table UNION SELECT null, avg(b), max(c) FROM table
C>
C>Насколько это идиоматично?
В целом, ИМХО, нормально, только я бы union на union all заменил.
Более правильно с логической точки зрения и быстрее.
Rollup не подойдёт, т.к. в общем случае он произведёт не такой же результат, что запрос выше.
"Потерял дар речи за зря"(с).
Re[2]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, _ABC_, Вы писали:
_AB>Rollup не подойдёт, т.к. в общем случае он произведёт не такой же результат, что запрос выше.
А в чём может быть разница? Если в порядке строк, до где-то пишут, что даже UNION ALL не обязан добавлять строку второго запроса имеено в конец выборки, а может поместить её в произвольном месте. Но ORDER BY решает проблему упорядочевания в обоих случаях.
Re[3]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, cppguard, Вы писали:
C>А в чём может быть разница?
В общем случае rollup собирает подытоги по указанным полям, это добавляет гибкости к запросу, но для предельного случая потребует некоторой подстройки.
Счастье — это Glück!
Re[4]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, Dym On, Вы писали:
C>>А в чём может быть разница? DO>В общем случае rollup собирает подытоги по указанным полям, это добавляет гибкости к запросу, но для предельного случая потребует некоторой подстройки.
Я если взять конкретный пример, то в чём разница?
SELECT id, qty, price FROM table
UNION ALL
SELECT null, sum(qty), avg(price) FROM TABLE
SELECT id, sum(qty), avg(price) FROM TABLE GROUP BY id WITH ROLLUP
Re[3]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, cppguard, Вы писали: C>А в чём может быть разница?
В производительности. UNION означает "без дубликатов", поэтому сервер обязан хранить все строки первого аргумента вплоть до порождения строки второго, а потом проверить, не совпадает ли она с какой-то из первых строк.
Запрос с UNION эквивалентен вот такому:
SELECT a, b, c
FROM (
SELECT a, b, c FROM table
UNION ALL
SELECT null, avg(b), max(c) FROM table
)
GROUP BY a, b, c
Очень немногие движки способны такое оптимизировать, даже если a — PK NOT NULL.
Ещё один побочный эффект — если (a, b, c) неуникальны (что на практике встречается исчезающе редко), то запрос с UNION ещё и вернёт меньше строк, чем с UNION ALL.
C>Если в порядке строк, до где-то пишут, что даже UNION ALL не обязан добавлять строку второго запроса имеено в конец выборки, а может поместить её в произвольном месте.
Без ORDER BY порядок строк запроса не определён, так что СУБД вольна отдавать данные так, как ей удобно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, cppguard, Вы писали:
C>Я если взять конкретный пример, то в чём разница? C>
C>SELECT id, qty, price FROM table
C>UNION ALL
C>SELECT null, sum(qty), avg(price) FROM TABLE
C>
C>
C>SELECT id, sum(qty), avg(price) FROM TABLE GROUP BY id WITH ROLLUP
C>
У ТС не id первой колонкой, а 'a', что будет, если 'a' не уникальная? Мы же не конкретный пример рассматриваем, а весьма общий.
C>Если в порядке строк, до где-то пишут Никогда не полагайся на порядок строк, возвращаемый по умолчанию. Это стандарт SQL.
Если нужен конкретный порядок, он задаётся order by или, допустим, на клиенте.
То, что сегодня работает неявно на конкретной версии, через 10 лет может не работать точно так же неявно на другой. А через 10 лет ты уже забудешь о том, почему ты это делал и как.
"Потерял дар речи за зря"(с).
Re[4]: Добавление аггрегации в вывод запроса через UNION
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, cppguard, Вы писали: C>>А в чём может быть разница? S>В производительности. UNION означает "без дубликатов", поэтому сервер обязан хранить все строки первого аргумента вплоть до порождения строки второго, а потом проверить, не совпадает ли она с какой-то из первых строк. S>Запрос с UNION эквивалентен вот такому: S>
S>SELECT a, b, c
S>FROM (
S> SELECT a, b, c FROM table
S> UNION ALL
S> SELECT null, avg(b), max(c) FROM table
S> )
S>GROUP BY a, b, c
S>
S>Очень немногие движки способны такое оптимизировать, даже если a — PK NOT NULL. S>Ещё один побочный эффект — если (a, b, c) неуникальны (что на практике встречается исчезающе редко), то запрос с UNION ещё и вернёт меньше строк, чем с UNION ALL.
C>>Если в порядке строк, до где-то пишут, что даже UNION ALL не обязан добавлять строку второго запроса имеено в конец выборки, а может поместить её в произвольном месте. S>Без ORDER BY порядок строк запроса не определён, так что СУБД вольна отдавать данные так, как ей удобно.
В общем случае (и по стандарту) это так, но в конкретных имплементациях (в том же постгресе) порядок можно зафиксировать.