Встановіть додатковий модуль 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);
Повернення:
Розділ | Активний | Неактивний
--------- + -------- + ----------
А | 1 | 2
Б | 4 | 5
C | 7 | - !!
- Не потрібно кастингу та перейменування.
- Зверніть увагу на неправильний результат для
C
: значення 7
заповнюється для першого стовпця. Іноді така поведінка є бажаною, але не для цього випадку використання.
- Проста форма також обмежена рівно трьома стовпцями у наданому вхідному запиті: ім'я рядка , категорія , значення . Немає місця для додаткових стовпців, як, наприклад, в 2-х параметрах нижче.
Безпечна форма
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
, $$VALUES ('Active'::text), ('Inactive')$$
) AS ct ("Section" text, "Active" int, "Inactive" int);
Повернення:
Розділ | Активний | Неактивний
--------- + -------- + ----------
А | 1 | 2
Б | 4 | 5
C | | 7 - !!
Зверніть увагу на правильний результат для C
.
Другий параметр може бути будь-яким запитом , який повертає один ряд на відповідність атрибута порядку визначення стовпця в кінці. Часто ви хочете запитувати різні атрибути з нижньої таблиці, як це:
'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
Це в посібнику.
Оскільки у будь-якому випадку вам потрібно прописати всі стовпці зі списку визначення стовпців (за винятком попередньо визначених варіантів), як правило, більш ефективно надати короткий список у виразі, як показано:crosstabN()
VALUES
$$VALUES ('Active'::text), ('Inactive')$$)
Або (не в посібнику):
$$SELECT unnest('{Active,Inactive}'::text[])$$ -- short syntax for long lists
Я використовував котирування в доларах, щоб полегшити котирування.
Ви можете навіть виводити стовпці з різними типами даних за умови crosstab(text, text)
, якщо текстове подання стовпця значення є коректним введенням для цільового типу. Таким чином , ви можете мати атрибути різних видів і продукції text
, date
, і numeric
т.д. для відповідних атрибутів. Приклад коду є в кінці розділу crosstab(text, text)
в посібнику .
db <> скрипка тут
Розширені приклади
\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
щоб забезпечити правильність упорядкування вхідних рядків