我有一张包含以下布局的表格:
ID Label Value
-- ----- -----
1 Lab1 Value1-1
1 Lab2 Value1-2
1 Lab3 Value1-3
1 Lab4 Value1-4
1 Lab5 Value1-5
1 Lab6 Value1-6
2 Lab1 Value2-1
2 Lab2 Value2-2
2 Lab3 Value2-3
2 Lab4 Value2-4
2 Lab5 Value2-5
2 Lab6 Value2-6
...
我想将表格转换成如下布局:
ID Lab1 Lab2 Lab3 Lab4 Lab5 Lab6
1 Value1-1 Value1-2 Value1-3 Value1-4 Value1-5 Value1-6
2 Value2-1 Value2-2 Value2-3 Value2-4 Value2-5 Value2-6
...
我在PostgreSQL中使用SQL。是否有一种简单(和内存有效)的方法来做到这一点? 我看过一些提到使用枢轴的帖子,但我不确定这是否有用,我看到的描述似乎是针对Oracle的。
答案 0 :(得分:3)
首先安装扩展程序tablefunc,如果您还没有。每个数据库需要完成一次。
CREATE EXTENSION tablefunc;
CREATE EXTENSION
需要PostgreSQL 9.1 。在旧版本中,您必须使用以下命令从shell运行安装脚本:
psql -d dbname -f SHAREDIR/contrib/tablefunc.sql
Postgres 9.0 in the fine manual的更多信息。
然后你可以使用像这样的查询:
SELECT *
FROM crosstab (
'SELECT id
,label
,value
FROM t
ORDER BY 1, 2',
'SELECT DISTINCT label
FROM t
ORDER BY 1')
AS tbl (
id int
,lab1 text
,lab2 text
,lab3 text
,lab4 text
,lab5 text
,lab6 text
);
准确地返回您要求的内容 您也可以为此创建一个功能。我在此closely related answer中添加了更多信息。
答案 1 :(得分:0)
如果您的SQL实现缺少转置/交叉表功能,您还可以通过以下方式展开/非规范化EAV:
SET search_path='tnp';
-- create some data ...
CREATE TABLE value
( id INTEGER NOT NULL
, attribute varchar
, value varchar
, PRIMARY KEY (id,attribute)
);
INSERT INTO value(id,attribute,value) VALUES
(1 ,'Lab1', 'Value1-1' )
, (1 ,'Lab2', 'Value1-2' )
, (1 ,'Lab3', 'Value1-3' )
, (1 ,'Lab4', 'Value1-4' )
, (1 ,'Lab5', 'Value1-5' )
, (1 ,'Lab6', 'Value1-6' )
, (2 ,'Lab1', 'Value2-1' )
, (2 ,'Lab2', 'Value2-2' )
, (2 ,'Lab3', 'Value2-3' )
, (2 ,'Lab4', 'Value2-4' )
, (2 ,'Lab5', 'Value2-5' )
, (2 ,'Lab6', 'Value2-6' )
;
SELECT v.id
, l1.value AS lab1
, l2.value AS lab2
, l3.value AS lab3
, l4.value AS lab4
, l5.value AS lab5
, l6.value AS lab6
FROM value v
LEFT JOIN value l1 ON l1.id = v.id AND l1.attribute = 'Lab1'
LEFT JOIN value l2 ON l2.id = v.id AND l2.attribute = 'Lab2'
LEFT JOIN value l3 ON l3.id = v.id AND l3.attribute = 'Lab3'
LEFT JOIN value l4 ON l4.id = v.id AND l4.attribute = 'Lab4'
LEFT JOIN value l5 ON l5.id = v.id AND l5.attribute = 'Lab5'
LEFT JOIN value l6 ON l6.id = v.id AND l6.attribute = 'Lab6'
;
我同意:这不是很优雅。但它确实有效。