Abd*_*ani 1 postgresql join pivot
我有两个表如下:
create table first (id int, name varchar(20));
create table second (id int, value char(1),fid int);
Run Code Online (Sandbox Code Playgroud)
这些表具有以下记录:
insert into first values (1,'Ahmad'),(2,'Sami'),(3,'Khan');
insert into second values
(1,'a',1)
, (2,'b',1)
, (3,'c',2)
, (4,'d',1)
, (5,'e',2)
, (6,'f',3);
Run Code Online (Sandbox Code Playgroud)
我想从表中选择那些在表second中具有匹配记录first的单行记录。
所需的输出是:
身份证 | 姓名 | 价值 | 价值 | 价值 ---+-------+-------+-------+------- 1 | 艾哈迈德 | | 乙 | d 2 | 萨米语 | | | 电子 | 3 | 汗 | f | |
table 的单个记录的值数量first不受限制, table 的单个记录可以有n多个值first。
n未知,但我需要为valuetablesecond中具有匹配记录的 table 中的每个值重复该列first。我需要像上面一样的整张桌子The desired result。我只需要 table 引用的那些行second。Postgres 的版本将是最新的。
其实,自从
ntable 的单个记录可以有多个值first。
要返回的列数并不是任意的。有最多列,这有一个干净的解决方案 - 除非你的列比Postgres 允许的表多:
250 - 1600 取决于列类型
顺便说一句,通常情况下,您还会有一个third表,列出 的所有可能值value,整个表实现了经典的多对多关系。
您可以使用CASE语句,或者更优雅地使用crosstab()附加模块的功能tablefunc。如果您不熟悉它,请先阅读此处的基本说明:
实际值右侧的列填充为 NULL。假设最多 5 个可能的值并以此设置为基础:
CREATE TABLE first (id int, name text);
CREATE TABLE second (id int, value "char", fid int);
INSERT INTO first VALUES
(1,'Ahmad')
, (2,'Sami')
, (3,'Khan')
, (4,'Nobody'); -- Added to demonstrate difference
INSERT INTO second VALUES
(1,'a',1)
, (2,'b',1)
, (3,'c',2)
, (4,'d',1)
, (5,'e',2)
, (6,'f',3);
Run Code Online (Sandbox Code Playgroud)
要么使用crosstab(text)(1个参数形式)并first再次加入表格:
SELECT id, f.name, value1, value2, value3, value4, value5
FROM crosstab(
'SELECT f.id, 1 AS dummy_category, s.value
FROM first f
JOIN second s ON s.fid = f.id
ORDER BY f.id, s.value'
) ct (id int
, value1 "char", value2 "char", value3 "char", value4 "char", value5 "char")
JOIN first f USING (id);
Run Code Online (Sandbox Code Playgroud)
或者使用crosstab(text, text)(2 个参数形式)并为您的值生成虚拟类别:
SELECT *
FROM crosstab(
'SELECT f.id, f.name
, row_number() OVER (PARTITION BY f.id ORDER BY s.value) AS dummy_category
, s.value
FROM first f
JOIN second s ON s.fid = f.id
ORDER BY f.id, s.value'
, ('SELECT generate_series(1,5)')
) ct (id int, name text
, value1 "char", value2 "char", value3 "char", value4 "char", value5 "char");
Run Code Online (Sandbox Code Playgroud)
结果是一样的:
id | name | value1 | value2 | value3 | value4 | value5
----+-------+--------+--------+--------+--------+--------
1 | Ahmad | a | b | d | |
2 | Sami | c | e | | |
3 | Khan | f | | | |
Run Code Online (Sandbox Code Playgroud)
如果您要包括所有从表行第一,使之成为LEFT [OUTER] JOIN:
...
LEFT JOIN second s ON s.fid = f.id
...
Run Code Online (Sandbox Code Playgroud)
然后我们为上面的例子得到一个额外的结果行:
4 | Nobody | | | | |
Run Code Online (Sandbox Code Playgroud)