отключить и PostgreSQL - PullRequest
25 голосов
/ 15 июля 2009

Есть ли в PostgreSQL эквивалентная функция, не являющаяся сводной?

Ответы [ 5 ]

80 голосов
/ 15 июня 2011

Создать пример таблицы:

CREATE TEMP TABLE foo (id int, a text, b text, c text);
INSERT INTO foo VALUES (1, 'ant', 'cat', 'chimp'), (2, 'grape', 'mint', 'basil');

Вы можете «отменить» или «открепить» с помощью UNION ALL:

SELECT id,
       'a' AS colname,
       a AS thing
FROM foo
UNION ALL
SELECT id,
       'b' AS colname, 
       b AS thing
FROM foo
UNION ALL
SELECT id, 
       'c' AS colname,
       c AS thing
FROM foo
ORDER BY id;

Это запускает 3 различных подзапроса в foo, по одному для каждого столбца, который мы хотим отменить, и возвращает в одной таблице каждую запись из каждого из подзапросов.

Но это отсканирует таблицу N раз, где N - количество столбцов, которые вы хотите отключить. Это неэффективно и является большой проблемой, когда, например, вы работаете с очень большой таблицей, сканирование которой занимает много времени.

Вместо этого используйте:

SELECT id,
       unnest(array['a', 'b', 'c']) AS colname,
       unnest(array[a, b, c]) AS thing
FROM foo
ORDER BY id;

Это легче написать, и он будет сканировать таблицу только один раз.

array[a, b, c] возвращает объект массива со значениями a, b и c в качестве его элементов. unnest(array[a, b, c]) разбивает результаты в одну строку для каждого из элементов массива.

Надеюсь, это поможет!

4 голосов
/ 14 августа 2014

К вашему сведению для тех из нас, кто ищет способ отмены в RedShift.

Полное решение формы, данное Стю, кажется, единственный способ сделать это.

https://forums.aws.amazon.com/thread.jspa?threadID=126369


Для тех, кто не может видеть это здесь, текст вставлен ниже ...

У нас нет встроенных функций, которые будут выполнять поворот или отключение. Тем не мение, Вы всегда можете написать SQL для этого.

create table sales (regionid integer, q1 integer, q2 integer, q3 integer, q4 integer);
insert into sales values (1,10,12,14,16), (2,20,22,24,26);

select * from sales order by regionid;

regionid | q1 | q2 | q3 | q4
----------+----+----+----+----
1 | 10 | 12 | 14 | 16
2 | 20 | 22 | 24 | 26

(2 rows)

сводный запрос

create table sales_pivoted (regionid, quarter, sales)
as
select regionid, 'Q1', q1 from sales
UNION ALL
select regionid, 'Q2', q2 from sales
UNION ALL
select regionid, 'Q3', q3 from sales
UNION ALL
select regionid, 'Q4', q4 from sales
;

select * from sales_pivoted order by regionid, quarter;

regionid | quarter | sales 
----------+---------+-------
1 | Q1 | 10
1 | Q2 | 12
1 | Q3 | 14
1 | Q4 | 16
2 | Q1 | 20
2 | Q2 | 22
2 | Q3 | 24
2 | Q4 | 26
(8 rows)

Отменить запрос

select regionid, sum(Q1) as Q1, sum(Q2) as Q2, sum(Q3) as Q3, sum(Q4) as Q4
from
(select regionid, 
case quarter when 'Q1' then sales else 0 end as Q1,
case quarter when 'Q2' then sales else 0 end as Q2,
case quarter when 'Q3' then sales else 0 end as Q3,
case quarter when 'Q4' then sales else 0 end as Q4
from sales_pivoted)

group by regionid
order by regionid;
regionid | q1 | q2 | q3 | q4 
----------+----+----+----+----
1 | 10 | 12 | 14 | 16
2 | 20 | 22 | 24 | 26
(2 rows)

Надеюсь, это поможет, Нил

3 голосов
/ 25 августа 2018

Вы можете использовать VALUES() и JOIN LATERAL, чтобы отключить столбцы.

Пример данных:

CREATE TABLE test(id int, a INT, b INT, c INT);
INSERT INTO test(id,a,b,c) VALUES (1,11,12,13),(2,21,22,23),(3,31,32,33);

Запрос:

SELECT t.id, s.col_name, s.col_value
FROM test t
JOIN LATERAL(VALUES('a',t.a),('b',t.b),('c',t.c)) s(col_name, col_value) ON TRUE;

Демоверсия DBFiddle

Используя этот подход, можно отключить несколько групп столбцов одновременно.

2 голосов
/ 14 мая 2010

Я написал ужасную функцию отмены вращения для PostgreSQL. Он довольно медленный, но, по крайней мере, возвращает результаты, как если бы вы ожидали, что операция отмены станет.

https://cgsrv1.arrc.csiro.au/blog/2010/05/14/unpivotuncrosstab-in-postgresql/

Надеюсь, вы найдете это полезным ..

1 голос
/ 09 апреля 2019

Извлечение слегка измененного содержимого из ссылки в комментарии из @a_horse_with_no_name в ответ, потому что это работает:

Установка Hstore Если у вас не установлен hstore и вы используете PostgreSQL 9.1+, вы можете использовать удобный

CREATE EXTENSION hstore;

Для более низких версий найдите файл hstore.sql в share / contrib и запустите его в своей базе данных.

Предполагая, что ваша исходная таблица (например, широкие данные) имеет один столбец 'id' с именем id_field и любое количество столбцов 'value' одного и того же типа, следующее создаст непивотированное представление этого Таблица.

CREATE VIEW vw_unpivot 
AS 
SELECT id_field, (h).key AS column_name, (h).value AS column_value
  FROM (SELECT id_field, each(hstore(foo) - 'id_field'::text) AS h
          FROM zcta5 as foo  
       ) AS unpiv ; 

Это работает с любым количеством столбцов 'value'. Все полученные значения будут текстовыми, если вы не произвели приведение, например, (h).value::numeric.

...