Несмотря на то, что вы хотите избежать функции crosstab()
, используйте агрегатное выражение FILTER
для лучшей производительности и четкого кода:
SELECT id, author
, sum(size) AS size
, count(*) FILTER (WHERE file_ext = 'python') AS python
, count(*) FILTER (WHERE file_ext = 'cpp') AS cpp
, count(*) FILTER (WHERE file_ext = 'non-code') AS "non-code"
FROM tablename
GROUP BY id, author;
Это самый быстрый способ с использованием только агрегатных функций. См .:
Для достижения максимальной производительности crosstab()
обычно быстрее, хотя в этом случае более многословно:
SELECT id, author, size
, COALESCE(python , 0) AS python
, COALESCE(cpp , 0) AS cpp
, COALESCE("non-code", 0) AS "non-code"
FROM crosstab(
$$
SELECT id, author
, sum(sum(size)) OVER (PARTITION BY id) AS size
, file_ext
, count(*) AS ct
FROM tablename
GROUP BY id, author, file_ext
ORDER BY id, author, file_ext
$$
, $$VALUES ('python'), ('cpp'), ('non-code')$$
) AS (id int, author text, size numeric
, python int, cpp int, "non-code" int);
Тот же результат.
дБ < > скрипка здесь - с промежуточными шагами .
Подробное объяснение:
О функции окна над функцией агрегирования (sum(sum(size)) OVER (...)
) см .:
Обратите внимание на небольшую разницу, если для одного и того же * 1054 должно быть несколько author
*: хотя первый запрос возвращает несколько строк в этом случае, вариант crosstab()
просто выбирает первого автора.