postgresql, именованные наборы группировок?
Есть ли способ назвать наборы группировки? Для каждого набора группировки (явно определенного или сгенерированного с помощью накопительного пакета или куба согласно https://www.postgresql.org/docs/devel/static/queries-table-expressions.html) я хотел бы как-то указать имя в столбец результата. Вот уродливая мгновенная демонстрация того, что я пытаюсь сделать, с именем, являющимся просто списком сгруппированных столбцов:
select *, array_to_string(array_remove(array[case when "A" is null then null else 'A' end,
case when "B" is null then null else 'B' end,
case when "C" is null then null else 'C' end
],null),',') as grouping_set
from (values ('a','b','c'),
('aa','bb','cc'),
('aaa',null,'ccc')) as foo("A","B","C")
group by rollup(1,2,3);
A | B | C | grouping_set
-----+----+-----+--------------
a | b | c | A,B,C
a | b | | A,B
a | | | A
aa | bb | cc | A,B,C
aa | bb | | A,B
aa | | | A
aaa | | ccc | A,C <--------- should be A,B,C
aaa | | | A <--------- should be A,B
aaa | | | A
| | |
Но обратите внимание, что есть проблема с двумя строками, помеченными стрелками: обе они включают столбец B в группировку, но не в имя, потому что в этих группах B пусто.
Есть идеи или лучшие способы обойти это?
2 ответа
SELECT "A", "B", "C",
CASE GROUPING("A", "B", "C")
WHEN 0 THEN 'A,B,C'
WHEN 1 THEN 'A,B'
WHEN 3 THEN 'A'
ELSE ''
END AS grouping_set
FROM (VALUES ('a','b','c'),
('aa','bb','cc'),
('aaa',null,'ccc')
) AS foo("A","B","C")
GROUP BY ROLLUP(1,2,3);
Соответствующая документация по группировке наборов согласно ответу Clodoaldo Neto.
Операции группировки используются вместе с наборами группировки (см. Раздел 7.2.4) для различения строк результатов. Аргументы операции GROUPING фактически не оцениваются, но они должны точно соответствовать выражениям, приведенным в предложении GROUP BY соответствующего уровня запроса. Биты назначаются с самым правым аргументом, являющимся младшим значащим битом; каждый бит равен 0, если соответствующее выражение включено в критерии группировки набора группировки, генерирующего строку результата, и 1, если это не так.
select *, grouping("A","B","C") as grouping_set
from (values
('a','b','c'),
('aa','bb','cc'),
('aaa',null,'ccc')
) as foo("A","B","C")
group by rollup(1,2,3);
A | B | C | grouping_set
-----+----+-----+--------------
a | b | c | 0
a | b | | 1
a | | | 3
aa | bb | cc | 0
aa | bb | | 1
aa | | | 3
aaa | | ccc | 0
aaa | | | 1
aaa | | | 3
| | | 7