sql - 如何将具有相同主键的多个表连接到每个键一行的表中?
问题描述
是)我有的
我有多个带有主键key
和值的表。每个键可能存在于所有表中或仅存在于表的子集中。
以下是示例表:
表 1:
钥匙 | 价值 |
---|---|
一种 | 1 |
C | 3 |
表 2:
钥匙 | 价值 |
---|---|
一种 | 10 |
D | 10 |
表 3:
钥匙 | 价值 |
---|---|
乙 | 20 |
D | 10 |
我想要的是
我想以这样一种方式加入这些表,即每个现有键得到一行,每个表得到一列。如果某个表中不存在某个键,null
则应假定该键。所以对于上面的例子,我想得到这个结果:
钥匙 | 选项卡1 | 选项卡2 | 选项卡3 |
---|---|---|---|
一种 | 1 | 10 | 空值 |
乙 | 空值 | 空值 | 20 |
C | 3 | 空值 | 空值 |
D | 空值 | 10 | 10 |
到目前为止我尝试过的
这是我想出的,它有效:
with tab1 as (
select * from (values('A', 1), ('C', 3))x(key, value)
),
tab2 as (
select * from (values('A', 10), ('D', 10))x(key, value)
),
tab3 as (
select * from (values('B', 20), ('D', 10))x(key, value)
)
select
coalesce(tab1.key, tab2.key, tab3.key) "key",
tab1.value tab1,
tab2.value tab2,
tab3.value tab3
from tab1
full outer join tab2 on tab2.key = tab1.key
full outer join tab3 on tab3.key = coalesce(tab1.key, tab2.key)
order by coalesce(tab1.key, tab2.key, tab3.key)
问题
在上面的例子中,我的查询看起来还不错,但是在实际情况下,我需要连接 6 个表,并且键实际上分布在三列中。这会导致很长的连接语句。第六个表的语句如下所示:
full outer join tab6
on tab6.key1 = coalesce(tab1.key1, tab2.key1, tab3.key1, tab4.key1, tab5.key1)
and tab6.key2 = coalesce(tab1.key2, tab2.key2, tab3.key2, tab4.key2, tab5.key2)
and tab6.key3 = coalesce(tab1.key3, tab2.key3, tab3.key3, tab4.key3, tab5.key3)
从代码质量的角度来看,复制和粘贴调用的激增coalesce
有些令人不安。
是否有另一种更简单的方法来获得我想要的结果?
解决方案
3张桌子的解决方案
WITH keys AS (
SELECT key FROM tab1 UNION
SELECT key FROM tab2 UNION
SELECT key FROM tab3
)
SELECT key, t1.value, t2.value, t3.value
FROM keys AS k
LEFT JOIN tab1 AS t1 USING (key)
LEFT JOIN tab2 AS t2 USING (key)
LEFT JOIN tab3 AS t3 USING (key)
对于下一个表,只需将其添加到 CTEkeys
中即可从所有表中获取所有出现的键。然后将此表附加到此 CTE 以获取值。
对于 10 个表,它仍然相当紧凑和合乎逻辑,最重要的是,添加更多表很容易:
WITH keys AS (
SELECT key FROM tab1 UNION
SELECT key FROM tab2 UNION
SELECT key FROM tab3 UNION
SELECT key FROM tab4 UNION
SELECT key FROM tab5 UNION
SELECT key FROM tab6 UNION
SELECT key FROM tab7 UNION
SELECT key FROM tab8 UNION
SELECT key FROM tab9 UNION
SELECT key FROM tab10
)
SELECT
key,
t1.value, t2.value, t3.value, t4.value, t5.value, t6.value, t7.value, t8.value, t9.value, t10.value
FROM keys AS k
LEFT JOIN tab1 AS t1 USING (key)
LEFT JOIN tab2 AS t2 USING (key)
LEFT JOIN tab3 AS t3 USING (key)
LEFT JOIN tab4 AS t4 USING (key)
LEFT JOIN tab5 AS t5 USING (key)
LEFT JOIN tab6 AS t6 USING (key)
LEFT JOIN tab7 AS t7 USING (key)
LEFT JOIN tab8 AS t8 USING (key)
LEFT JOIN tab9 AS t9 USING (key)
LEFT JOIN tab10 AS t10 USING (key)
有一个小提琴: https ://www.db-fiddle.com/f/9aa2wUtR2RbQaGKTtXrr1W/1
或在您可以获得所有键和连接值时创建一个视图,或使用 FULL JOIN(请参阅 Lukas 的解决方案)
推荐阅读
- datastage - 如果一条记录满足 Transformer 阶段中指定的约束,如何将所有记录导出到 DataStage 上的顺序文件?
- kubernetes - 带有 Calico 的 k8s,POD 容器无法在 ip 外 ping
- python - 如果他们在django中成功登录,如何制作解锁屏幕功能并在锁定之前参考他们打开的上一页
- python-3.x - 在 Pytorch 中为 HDF5 文件创建数据集和数据加载器时遇到问题:没有足够的值来解包(预期 2,得到 1)
- php - 从 jquery 购物车中获取余额
- javascript - 有没有办法使用 JavaScript 获取孩子的父母姓名?
- android - 由于没有窗口焦点而丢弃事件:MotionEvent 和由于没有窗口焦点而取消事件:MotionEvent
- python - Telethon:如何获得私人频道的邀请链接?
- c - 从C中的父进程获取子值(退出代码)
- java - 使用 MongoDB Java 驱动程序运行 MongoDB 脚本