我正在尝试在Postgres中构建一个使用3个表的数据的视图。我不确定这是否可能,并在谷歌搜索了一些但没有找到任何结论。这就是我想要做的事情:
我有一个项目名称表 - 比方说有5个项目:
fruits
id | name
1 | banana
2 | orange
3 | pear
4 | apple
5 | grape
然后我有一个人员列表
people
id | name
1 | Joe Blow
2 | Sally Smith
3 | John Jones
4 | Sam Benny
5 | Nick Stevens
6 | Peter Sandwitch
7 | Sarah Morgan
然后我有第三个表连接上面两个:
people_fruits
person_id | fruit_id
1 | 1
1 | 2
1 | 3
1 | 4
2 | 1
2 | 3
3 | 5
6 | 3
7 | 3
7 | 4
我要做的是能够使用上面的内容动态创建视图,该视图将根据水果表的内容更改列。例如,我希望视图显示以上数据如下:
my_fruity_view
name | bananna | orange | pear | apple | grape
Joe Blow | X | X | X | X |
Sally Smith | X | | X | |
John Jones | | | | | X
Sam Benny | | | | |
Nick Stevens | | | | |
Peter Sandwitch | | | X | |
Sarah Morgan | | | X | X |
然后,如果我稍后要添加水果芒果,下次运行查询(不做修改),它会将其添加为一列:
my_fruity_view
name | bananna | orange | pear | apple | grape | mango
Joe Blow | X | X | X | X | |
Sally Smith | X | | X | | |
John Jones | | | | | X |
Sam Benny | | | | | |
Nick Stevens | | | | | |
Peter Sandwitch | | | X | | |
Sarah Morgan | | | X | X | |
这样的查询可能吗?我在堆栈溢出时看到了类似的一些东西 - 但它似乎是基于每列完成的 - 但我的数据需要是动态的。
我可以通过编程实现这一目标,但我更愿意将其打包成一个整洁的视图。任何有关这方面的帮助将不胜感激。
答案 0 :(得分:1)
基本上您需要 pivot 表或交叉列表。附加模块tablefunc
提供您需要的功能。如果您不熟悉它,请先阅读:
你的案例的特殊困难:你首先需要一个连接表的查询来产生正确的输入:
SELECT p.name, f.name, text 'x' AS marker -- required, logically redundant column
FROM people p
LEFT JOIN people_fruits pf ON pf.person_id = p.id -- LEFT JOIN !
LEFT JOIN fruits f ON f.id = pf.fruit_id
ORDER BY p.id, f.id; -- seems to be the desired sort order
LEFT [OUTER] JOIN
,所以你不会失去没有水果的人。
在crosstab()
函数中使用两个参数,如下所示:
SELECT * FROM crosstab(
$$SELECT p.name, f.name, text 'x'
FROM people p
LEFT JOIN people_fruits pf ON pf.person_id = p.id
LEFT JOIN fruits f ON f.id = pf.fruit_id
ORDER BY p.id$$
,$$VALUES ('bananna'), ('orange'), ('pear'), ('apple'), ('grape')$$)
AS ct (name text, bananna text, orange text, pear text, apple text, grape text);
目标列列表中水果的顺序必须与第二个参数中水果的顺序相匹配(在您的情况下按id
排序)。
缺少水果获得NULL
值。
但是,这还不是动态。 SQL完全不能完全动态,这需要在调用时知道结果列。无论如何,您需要两次往返DB服务器。您可以让Postgres动态构建交叉表查询,然后在下一步中执行它。
代码示例的相关答案:
替代将返回包含动态的数组或文档类型(json
,xml
,...)元素列表。