Установите дополнительный модуль tablefunc
один раз на базу данных, которая обеспечивает функцию crosstab()
. Начиная с Postgres 9.1, вы можете использовать CREATE EXTENSION
для этого:
CREATE EXTENSION IF NOT EXISTS tablefunc;
Улучшенный контрольный пример
CREATE TABLE tbl (
section text
, status text
, ct integer -- "count" is a reserved word in standard SQL
);
INSERT INTO tbl VALUES
('A', 'Active', 1), ('A', 'Inactive', 2)
, ('B', 'Active', 4), ('B', 'Inactive', 5)
, ('C', 'Inactive', 7); -- ('C', 'Active') is missing
Простая форма - не подходит для отсутствующих атрибутов
crosstab(text)
с 1 входной параметр:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- needs to be "ORDER BY 1,2" here
) AS ct ("Section" text, "Active" int, "Inactive" int);
Возвращает:
Section | Active | Inactive
---------+--------+----------
A | 1 | 2
B | 4 | 5
C | <b>7</b> | -- !!
- Нет необходимости кастовать и переименовывать.
- Обратите внимание на неправильный результат для
C
: значение 7
заполнено для первого столбца. Иногда такое поведение желательно, но не для этого варианта использования.
- Простая форма также ограничена точно тремя столбцами в предоставленном входном запросе: имя_ строки , категория , значение . Нет места для дополнительных столбцов , как в альтернативе с двумя параметрами ниже.
Безопасная форма
crosstab(text, text)
с 2 входные параметры:
SELECT *
FROM crosstab(
'SELECT section, status, ct
FROM tbl
ORDER BY 1,2' -- could also just be "ORDER BY 1" here
<b>, $$VALUES ('Active'::text), ('Inactive')$$</b>
) AS ct ("Section" text, "Active" int, "Inactive" int);
Возвращает:
Section | Active | Inactive
---------+--------+----------
A | 1 | 2
B | 4 | 5
C | | <b>7</b> -- !!
Обратите внимание на правильный результат для C
.
Второй параметр может быть любым запросом, который возвращает одну строку на атрибут, соответствующий порядку определения столбца в конце. Часто вам нужно запросить отдельные атрибуты из базовой таблицы, например так:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
Это в руководстве.
Так как вам все равно нужно прописать все столбцы в списке определений столбцов (за исключением предопределенных вариантов crosstab<i>N</i>()
), обычно более эффективно предоставлять короткий список в выражении VALUES
, как показано:
$$VALUES ('Active'::text), ('Inactive')$$)
Или (не в руководстве):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
Я использовал цитирование в долларах , чтобы упростить цитирование.
Вы даже можете выводить столбцы с различными типами данных с crosstab(text, text)
- при условии, что текстовое представление столбца значения является допустимым вводом для целевого типа. Таким образом, вы можете иметь атрибуты различного вида и выводить text
, date
, numeric
и т. Д. Для соответствующих атрибутов. В конце главы crosstab(text, text)
приведен пример кода .
дБ <> скрипка здесь
Расширенные примеры
\crosstabview
в psql
Postgres 9.6 добавил эту мета-команду к своему интерактивному терминалу по умолчанию psql . Вы можете запустить запрос, который вы будете использовать в качестве первого crosstab()
параметра, и передать его в \crosstabview
(немедленно или на следующем шаге). Как:
db=> SELECT section, status, ct FROM tbl \crosstabview
Результат, аналогичный приведенному выше, но это функция представления исключительно на стороне клиента . Входные строки обрабатываются немного по-разному, поэтому ORDER BY
не требуется. Подробная информация о \crosstabview
приведена в руководстве. Внизу этой страницы приведено еще несколько примеров кода.
Соответствующий ответ на dba.SE Дэниела Верите (автора функции psql):
ранее принятый ответ устарел.
Вариант функции crosstab(text, integer)
устарел. Второй параметр integer
игнорируется. Я цитирую текущее руководство :
crosstab(text sql, int N)
...
Устаревшая версия crosstab(text)
. Параметр N
теперь игнорируется,
поскольку количество столбцов значений всегда определяется вызывающим запросом
Ненужное приведение и переименование.
Сбой, если строка не имеет всех атрибутов.См. Безопасный вариант с двумя входными параметрами выше для правильной обработки отсутствующих атрибутов.
ORDER BY
требуется в форме с одним параметром crosstab()
. Руководство:
На практике в запросе SQL всегда следует указывать ORDER BY 1,2
, чтобы обеспечить правильную упорядоченность входных строк