#sql #postgresql #sum
Вопрос:
у меня довольно сложный вложенный запрос, который структурирован следующим образом:
select descr, sum(percentage) as perc from
( COMPLEX QUERY HERE)
as A group by descr order by perc desc
результат этого запроса таков:
descr perc
------------------------------------
bottom (1 * 18 cm²) 2.77
totalarea (1 * 70 cm²) 2.49
innerwalls (1 * 22 cm²) 2.37
bottom (2 * 12 cm²) 1.55
innerwalls (2 * 17 cm²) 1.51
risperror 0.29
totalnumberdefects (1 * 30 cm²) 0.00
clipserror 0.00
outerwalls (1 * 18 cm²) 0.00
outerwalls (2 * 16 cm²) 0.00
Теперь мне нужно будет добавить столбец, содержащий Sum() perc , поэтому в этом случае я ожидал бы этого в результате:
descr perc sum
------------------------------------------------
bottom (1 * 18 cm²) 2.77 10.98
totalarea (1 * 70 cm²) 2.49 10.98
innerwalls (1 * 22 cm²) 2.37 10.98
bottom (2 * 12 cm²) 1.55 10.98
innerwalls (2 * 17 cm²) 1.51 10.98
risperror 0.29 10.98
totalnumberdefects (1 * 30 cm²) 0.00 10.98
clipserror 0.00 10.98
outerwalls (1 * 18 cm²) 0.00 10.98
outerwalls (2 * 16 cm²) 0.00 10.98
учитывая, что запрос действительно сложный и медленный, я хотел бы добавить указанный выше столбец, начав с результата приведенного выше запроса, без необходимости повторно вызывать тот же запрос для получения результатов.
Как это можно сделать?
Комментарии:
1. Какую СУБД вы используете?
2. @jarlh Я использую dbeaver 7.3.4 в базе данных postre
3. Я не знаком с этой СУБД. Поддерживает ли он ANSI SQL? Если это так, я полагаю, вы могли бы использовать общее табличное выражение, чтобы изолировать сложный запрос и вывести из него как свои
perc
, так иtotal
столбцы.4. Вы можете прочитать о CTE здесь , или я мог бы написать пример ответа.
Ответ №1:
Вы можете использовать функцию окна СУММЫ для вашего результата:
WITH myquery AS (
select descr, sum(percentage) as perc from
( COMPLEX QUERY HERE)
as A group by descr order by perc desc
)
SELECT *, SUM(perc) OVER () AS "sum"
FROM myquery
Комментарии:
1. (Комментарий к оригинальному постеру, @sharkyenergy) Это показывает использование CTE, аналогично тому, что я бы сделал.
2. Большое вам спасибо, никогда не слышал об утверждении «over». посмотрим на это!
Ответ №2:
Использовать sum()
с функцией as window:
SELECT *,SUM(perc) OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM (your_complex_sql_query) j
Фрейм RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
в этом случае необязателен, поскольку фрейм не имеет порядка или раздела, но считается хорошей практикой делать вещи явными. Таким образом, вы также можете просто использовать OVER ()
SELECT *,SUM(perc) OVER ()
FROM (your_complex_sql_query) j
ДЕМОНСТРАЦИЯ: db<>fiddle
Ответ №3:
Без использования group by:
Раньше я window function sum()
получал общее perc и общее perc с помощью descr.
SELECT DISTINCT descr,
SUM(perc) OVER (PARTITION BY descr) AS perc,
SUM(perc) OVER () AS "sum"
FROM (COMPLEX QUERY HERE) AS sq;
Или с помощью CTE
:
WITH cte AS (COMPLEX QUERY HERE)
SELECT DISTINCT descr,
SUM(perc) OVER (PARTITION BY descr) AS perc,
SUM(perc) OVER () AS "sum"
FROM cte;
Комментарии:
1. Почему вы используете
DISTINCT
?SELECT descr, SUM(perc), SUM(SUM(perc)) OVER () FROM cte GROUP BY descr
кажется, имеет гораздо больше смысла?2. Да, это так, потому что я не группирую по, поэтому, если вы не используете
DISTINCT
, у вас не будет строки по описанию. Вы можете проверить это здесь3. Я знаю, что это работает, это просто очень своеобразный шаблон; вы создаете повторяющиеся строки, а затем удаляете их, где агрегаты as не имеют таких накладных расходов.
4. Нет, я не создаю повторяющиеся строки, строки находятся в таблице (в complex_subquery). Таким образом, я избегаю использования дополнительного подзапроса.
5. @MatBailie проверьте принятый ответ, он использовал на один подзапрос больше, чем я, чтобы получить тот же результат. Это другой подход.