Как считать, когда не знаешь конкретных типов

Я работаю над таблицей вроде этого:

id type
1 A
2 A
3 B
4 C
5 C

Я хотел подсчитать количество идентификаторов для каждого типа и получить такую ​​​​таблицу.

type_a type_b type_c
2 1 2

То, что я сделал, было

SELECT 
    SUM(CASE WHEN type = 'A' THEN 1 ELSE 0 END) AS type_a,
    SUM(CASE WHEN type = 'B' THEN 1 ELSE 0 END) AS type_b,
    SUM(CASE WHEN type = 'C' THEN 1 ELSE 0 END) AS type_c
FROM myTable

Мой вопрос: если я не знаю, сколько существует типов, и не могу конкретно перечислить все случаи, как я могу этого добиться?


person Erin Liu    schedule 16.04.2021    source источник
comment
Было бы намного проще вернуть результат в виде двух столбцов: Type, Count.   -  person Janez Kuhar    schedule 16.04.2021
comment
тогда вам нужно использовать динамический sql   -  person eshirvana    schedule 16.04.2021
comment
Отвечает ли это на ваш вопрос? Динамический сводной запрос с использованием PostgreSQL 9.3   -  person PM 77-1    schedule 16.04.2021


Ответы (2)


Вы ищете перекрестную таблицу или сводную таблицу. Я добавил теги.
Однако:

если я не знаю, сколько существует типов, и не могу конкретно перечислить все случаи, как я могу этого добиться?

В принципе это невозможно в одном SQL-запросе, потому что SQL требует знать количество столбцов результатов во время вызова. Он не может вернуть динамическое количество столбцов в принципе.

Существуют различные обходные пути с полиморфными типами или с типом документа, таким как json, jsonb, hstore или xml, или с возвращаемыми массивами вместо отдельных столбцов...

Но чтобы получить именно то, что вы просите, неизвестное количество выделенных столбцов, вам нужен двухэтапный рабочий процесс. Нравиться:

  1. Создайте запрос динамически (определив тип возвращаемого значения).
  2. Выполните это.

Связанный:

Тем не менее, если ваш случай простой и вы имеете дело с кучей известных типов, вы можете просто предоставить лишнее. С более быстрым запросом crosstab() или с простой условной агрегацией, как у вас, просто более элегантной и эффективной с предложением агрегата FILTER:

SELECT count(*) FILTER (WHERE type = 'A') AS type_a
     , count(*) FILTER (WHERE type = 'B') AS type_b
     , count(*) FILTER (WHERE type = 'C') AS type_c
     , count(*) FILTER (WHERE type = 'D') AS type_d
     -- that's all folks!
FROM   tbl;

Типы без записей сообщают 0 (count() никогда не возвращает NULL), что в любом случае было бы правильным.

Не работает для неизвестных типов, очевидно.

person Erwin Brandstetter    schedule 17.04.2021

Если я правильно вас понял, все, что вам нужно, это простой COUNT:

SELECT
    type
    ,COUNT(id)
FROM myTable
GROUP BY type
person Don R    schedule 16.04.2021
comment
Есть еще несколько столбцов, которые я хочу добавить. Например: количество, процент и т. д., и хотелось бы, чтобы для каждого столбца это был тип, для первой строки — количество каждого типа, а для второй строки — процент каждого типа. (процент = количество каждого типа / общее количество идентификаторов). - person Erin Liu; 17.04.2021