使一对多关系看起来像一对一
Posted
技术标签:
【中文标题】使一对多关系看起来像一对一【英文标题】:Make one-to-many relationship look like one-to-one 【发布时间】:2014-08-13 13:33:57 【问题描述】:我正在使用 postgres 9.3.5。
给定以下数据:
select * from department;
id | name
----+-----------
1 | sales
2 | marketing
3 | HR
和
select * from people;
id | department_id | first_name | last_name
----+---------------+------------+-----------
1 | 1 | Tom | Jones
2 | 1 | Bill | Cosby
3 | 2 | Jessica | Biel
4 | 1 | Rachel | Hunter
5 | 2 | John | Barnes
我想返回一个这样的结果集:
id | name | first_name-1 | last_name-1 | first_name-2 | last_name-2 | first_name-3 | last_name-3
----+-----------+--------------+-------------+--------------+-------------+--------------+------------
1 | sales | Tom | Jones | Bill | Cosby | Rachel | Hunter
2 | marketing | Jessica | Biel | John | Barnes
3 | HR |
这可能吗?
Max Shawabkeh 使用 GROUP_CONCAT 提供的here 答案很接近 - 但它不会作为数据集中的额外字段返回,而是将它们连接成一个字段。
【问题讨论】:
【参考方案1】:您需要交叉制表(有时称为pivot)。
在您的情况下可能如下所示:
SELECT * FROM crosstab(
$$SELECT d.id, d.name,'p' AS dummy_cat
,concat_ws(' ', p.first_name, p.last_name) AS person
FROM department d
LEFT JOIN people p ON p.department_id = d.id
ORDER BY d.department_id, p.id$$
)
AS ct (id int, department text, person_1 text, person_2 text, person_3 text);
返回:
id department person_1 person_2 person_3
--------------------------------------------------------
1 sales Tom Jones Bill Cosby Rachel Hunter
2 marketing Jessica Biel John Barnes <NULL>
3 HR <NULL> <NULL> <NULL>
非常和这个相关案例很相似(有特殊困难的说明):
Postgres - Transpose Rows to Columns但这种情况更简单:由于您似乎并不关心人员列出的顺序,因此您可以使用crosstab()
的基本单参数形式。
另外,根据您的评论,您需要所有部门,即使没有分配任何人。相应地调整了 LEFT JOIN。
此相关答案中的基本细节:
PostgreSQL Crosstab Query【讨论】:
感谢 Erwin,非常接近我正在寻找的输出 - 缺少 HR 的 NULL 行以及 first_name 和 last_name 的单独列。 @CodeBuddy:我反转了LEFT JOIN
以包括空部门并简化了查询。分开的名字,也可以解决。在外部查询中分解。
再次感谢,但新查询对我返回错误:错误:d.department_id 列不存在
@CodeBuddy: 显然是d.id
(在我自己的设计中,我从不使用“id”或“name”等非描述性词语作为标识符。)以上是关于使一对多关系看起来像一对一的主要内容,如果未能解决你的问题,请参考以下文章