PostgreSQL 上的数据透视行
Pivot Row on PostgreSQL
我有一个 return 整行的查询,我需要将此结果转换为新的 table。
SELECT id_no, stud_name, group_no, class_1, class_2, class_3, class_4 FROM tbl_stud_class
这 return 如下:
| id_no | stud_name | group_no | class_1 | class_2 | class_3 | class 4 |
| 1 | John Doe | A11 | 84 | 60 | 80 | 79 |
我需要能够return这一行:
| id_no | stud_name | group_no | class | grade |
| 1 | John Doe | A11 | class_1 | 84 |
| 1 | John Doe | A11 | class_2 | 60 |
| 1 | John Doe | A11 | class_3 | 80 |
| 1 | John Doe | A11 | class_4 | 79 |
有人能告诉我一个方法吗?
我是 PostgreSQL 的新手,所以我不知道从哪里开始以及如何开始。
谢谢!
需要这个:
WITH tbl_stud_class
(id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
(
VALUES
(1, 'John Doe', 'All', 84, 60, 80, 79),
(2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
)
SELECT
id_no, stud_name, group_no, 'class_1' AS class, class_1 AS grade
FROM
tbl_stud_class
WHERE
class_1 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_2' AS class, class_2 AS grade
FROM
tbl_stud_class
WHERE
class_2 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_3' AS class, class_3 AS grade
FROM
tbl_stud_class
WHERE
class_3 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_4' AS class, class_4 AS grade
FROM
tbl_stud_class
WHERE
class_4 IS NOT NULL
ORDER BY
id_no, class ;
AFAIK,没有办法以自动方式执行此操作。 PostgreSQL 有 crosstab
函数,它执行 PIVOT,但它以相反的方式工作(从您想要的输出到您的输入)。
你有一个更短的选择,使用 arrays
and unnest
:
WITH tbl_stud_class
(id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
(
VALUES
(1, 'John Doe', 'All', 84, 60, 80, 79),
(2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
)
SELECT
*
FROM
(
SELECT
id_no, stud_name, group_no,
unnest(ARRAY['class_1', 'class_2', 'class_3', 'class_4']) AS class,
unnest(ARRAY[ class_1, class_2, class_3, class_4 ]) AS grade
FROM
tbl_stud_class
) AS s0
WHERE
grade is not null
ORDER BY
id_no, class ;
你也可以在postgresql 9.3+
中使用LATERAL
SELECT id_no, stud_name, group_no, class, grade
FROM tbl_stud_class
CROSS JOIN LATERAL ( VALUES
('class_1', class_1),
('class_2', class_2),
('class_3', class_3),
('class_4', class_4)
) l(class, grade)
我有一个 return 整行的查询,我需要将此结果转换为新的 table。
SELECT id_no, stud_name, group_no, class_1, class_2, class_3, class_4 FROM tbl_stud_class
这 return 如下:
| id_no | stud_name | group_no | class_1 | class_2 | class_3 | class 4 |
| 1 | John Doe | A11 | 84 | 60 | 80 | 79 |
我需要能够return这一行:
| id_no | stud_name | group_no | class | grade |
| 1 | John Doe | A11 | class_1 | 84 |
| 1 | John Doe | A11 | class_2 | 60 |
| 1 | John Doe | A11 | class_3 | 80 |
| 1 | John Doe | A11 | class_4 | 79 |
有人能告诉我一个方法吗? 我是 PostgreSQL 的新手,所以我不知道从哪里开始以及如何开始。
谢谢!
需要这个:
WITH tbl_stud_class
(id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
(
VALUES
(1, 'John Doe', 'All', 84, 60, 80, 79),
(2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
)
SELECT
id_no, stud_name, group_no, 'class_1' AS class, class_1 AS grade
FROM
tbl_stud_class
WHERE
class_1 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_2' AS class, class_2 AS grade
FROM
tbl_stud_class
WHERE
class_2 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_3' AS class, class_3 AS grade
FROM
tbl_stud_class
WHERE
class_3 IS NOT NULL
UNION
SELECT
id_no, stud_name, group_no, 'class_4' AS class, class_4 AS grade
FROM
tbl_stud_class
WHERE
class_4 IS NOT NULL
ORDER BY
id_no, class ;
AFAIK,没有办法以自动方式执行此操作。 PostgreSQL 有 crosstab
函数,它执行 PIVOT,但它以相反的方式工作(从您想要的输出到您的输入)。
你有一个更短的选择,使用 arrays
and unnest
:
WITH tbl_stud_class
(id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
(
VALUES
(1, 'John Doe', 'All', 84, 60, 80, 79),
(2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
)
SELECT
*
FROM
(
SELECT
id_no, stud_name, group_no,
unnest(ARRAY['class_1', 'class_2', 'class_3', 'class_4']) AS class,
unnest(ARRAY[ class_1, class_2, class_3, class_4 ]) AS grade
FROM
tbl_stud_class
) AS s0
WHERE
grade is not null
ORDER BY
id_no, class ;
你也可以在postgresql 9.3+
中使用LATERALSELECT id_no, stud_name, group_no, class, grade
FROM tbl_stud_class
CROSS JOIN LATERAL ( VALUES
('class_1', class_1),
('class_2', class_2),
('class_3', class_3),
('class_4', class_4)
) l(class, grade)