连接两个表并在一行中合并多个关联

Posted

技术标签:

【中文标题】连接两个表并在一行中合并多个关联【英文标题】:Join two tables and merge multiple associations in one row 【发布时间】:2017-10-06 13:35:49 【问题描述】:

我目前在连接两个 PSQL 表时遇到问题。我知道一直有人问这类问题,但是我找不到适用于我情况的答案。对于模糊的问题标题,我深表歉意。

描述简化的情况:我们有两个表,childrenparents。如您所见,孩子们通过逗号分隔的“数组”中的 ID 链接到他们的父母。我想创建一个简单的视图(非物化),从孩子的角度来看,父母与他们的孩子在一起。

桌孩子

| id | name  | parents |
| -- | ----- | ------- |
| 1  | Bob   | 1,2     |
| 2  | Alice | 3       |

表父母

| id | name  | phone |
| -- | ----- | ----- |
| 1  | Carol | 1234  |
| 2  | Frank | 5678  |
| 3  | Grace | 9012  |

想要的组合视图

| child_id | child_name | parent1_name | parent1_phone | parent2_name | parent2_phone |
| -------- | ---------- | ------------ | ------------- | ------------ | ------------- |
| 1        | Bob        | Carol        | 1234          | Frank        | 5678          |
| 2        | Alice      | Grace        | 9012          |              |               |

我尝试使用以下视图定义来实现上述目标:

SELECT children.id AS child_id,
    children.name AS child_name,
    parents.name AS parent_name,
    parents.phone AS parent_phone
   FROM children
     JOIN parents ON parents.id::text = 
       ANY (string_to_array(children.parents, ','::text));

这当然不会将孩子的两个父母合并为一行:

| child_id | child_name | parent_name | parent_phone |
| 1        | Bob        | Carol       | 1234         |
| 1        | Bob        | Frank       | 5678         |
| 2        | Alice      | Grace       | 9012         |

什么是我想要的结果的最佳解决方案?

【问题讨论】:

【参考方案1】:

您需要在当前查询之后创建一些聚合

SQL DEMO

WITH cte as (
    SELECT *, row_number() over (partition by child_id order by "parent_name") as rn
    FROM queryResult
)
SELECT child_id, 
       child_name, 
       MAX( CASE WHEN rn = 1 then parent_name END) as parent_name_1,
       MAX( CASE WHEN rn = 1 then parent_phone END) as parent_phone_1,
       MAX( CASE WHEN rn = 2 then parent_name END) as parent_name_2,
       MAX( CASE WHEN rn = 2 then parent_phone END) as parent_phone_2
FROM cte
GROUP BY child_id, child_name
ORDER BY child_id

输出

注意: 这假设一个孩子最多只有 2 个父母。因此,如果您过度简化问题或数据中包含现代家庭,请务必小心。

【讨论】:

感谢胡安的回答。不幸的是,我的数据库包含许多现代家庭;)我大大简化了我的问题。实际上,我的“孩子”最多可以有 5 个父母(但也为零)。 “父母”表中的行最多包含我要在视图中合并的 5 列。这将使您提供的查询对我来说非常麻烦。在处理更大的族和更多的父数据列时,有没有办法缩短或简化您的查询? 是的,我想这可能是个问题。但是如果是up to 5 我仍然认为可以工作。但是你也有交叉表功能(你需要添加一个扩展)检查这个tutorial

以上是关于连接两个表并在一行中合并多个关联的主要内容,如果未能解决你的问题,请参考以下文章

如何使用枢轴连接两个表并在一个表中组合两个字段

如何基于 ManyToManyField 内部连接表并按参数分组并在 Django 中获取最新的表?

连接两个表并从一列返回多个匹配项的 SQL 查询?

如何连接多个表,包括查找表并按行返回数据

SQL 连接两个表并检查两个表中的每个值是不是存在

多表合并且去掉重复项