SQL连接:无需别名拆分同名列(数据不同)的行
问题描述
现有三张表t1、t2、t3,其中t1和t3的client_id、transmission_id、timestamp完全匹配,但t2的timestamp与前两者存在差异。需要将三张表连接后,把不同的timestamp拆分为独立行,得到单一timestamp列的结果,而非保留多列时间戳的形式。
表结构
t1:
| client_id | transmission_id | timestamp | column_A |
|---|---|---|---|
| 1 | AAA1 | 2024-10-16 10:31:27 | Banana |
| 1 | AAA2 | 2024-10-16 11:31:27 | Citrus |
| 2 | BBB1 | 2024-10-16 09:12:14 | Apple |
t2:
| client_id | transmission_id | timestamp | column_B |
|---|---|---|---|
| 1 | AAA1 | 2024-10-16 10:41:27 | Paris |
| 1 | AAA2 | 2024-10-16 11:41:27 | London |
| 2 | BBB1 | 2024-10-16 09:22:14 | NY |
t3:
| client_id | transmission_id | timestamp | column_C |
|---|---|---|---|
| 1 | AAA1 | 2024-10-16 10:31:27 | Eat |
| 1 | AAA2 | 2024-10-16 11:31:27 | Pray |
| 2 | BBB1 | 2024-10-16 09:12:14 | Love |
期望结果
| client_id | transmission_id | timestamp | column_A | column_B | column_C |
|---|---|---|---|---|---|
| 1 | AAA1 | 2024-10-16 10:31:27 | Banana | Eat | |
| 1 | AAA1 | 2024-10-16 10:41:27 | Paris | ||
| 1 | AAA2 | 2024-10-16 11:31:27 | Citrus | Pray | |
| 1 | AAA2 | 2024-10-16 11:41:27 | London | ||
| 2 | BBB1 | 2024-10-16 09:12:14 | Apple | Love | |
| 2 | BBB1 | 2024-10-16 09:22:14 | NY |
此前尝试保留多列时间戳的方式(如下),但复杂场景下难以追踪时间线,因此需要优化:
| client_id | transmission_id | t1_t3.timestamp | t2.timestamp | column_A | column_B | column_C |
|---|---|---|---|---|---|---|
| 1 | AAA1 | 2024-10-16 10:31:27 | 2024-10-16 10:41:27 | Banana | Paris | Eat |
| 1 | AAA2 | 2024-10-16 11:31:27 | 2024-10-16 11:41:27 | Citrus | London | Pray |
| 2 | BBB1 | 2024-10-16 09:12:14 | 2024-10-16 09:22:14 | Apple | NY | Love |
解决方案
可以通过合并所有时间戳行,再关联各表数据的方式实现。以下是通用SQL示例(以MySQL为例,其他数据库语法可微调):
-- 生成所有唯一的(client_id, transmission_id, timestamp)组合 WITH all_timepoints AS ( SELECT client_id, transmission_id, timestamp FROM t1 UNION SELECT client_id, transmission_id, timestamp FROM t2 UNION SELECT client_id, transmission_id, timestamp FROM t3 ) SELECT at.client_id, at.transmission_id, at.timestamp, t1.column_A, t2.column_B, t3.column_C FROM all_timepoints at LEFT JOIN t1 ON at.client_id = t1.client_id AND at.transmission_id = t1.transmission_id AND at.timestamp = t1.timestamp LEFT JOIN t2 ON at.client_id = t2.client_id AND at.transmission_id = t2.transmission_id AND at.timestamp = t2.timestamp LEFT JOIN t3 ON at.client_id = t3.client_id AND at.transmission_id = t3.transmission_id AND at.timestamp = t3.timestamp ORDER BY at.client_id, at.transmission_id, at.timestamp;
逻辑说明
- 用
WITH子句创建临时表all_timepoints,通过UNION去重合并三张表中所有时间点组合,确保每个独立时间戳都成为一行。 - 将临时表与三张源表分别做左连接,仅匹配相同
client_id、transmission_id和timestamp的行,对应列自动填充数据,不匹配的列则为NULL。 - 最后按
client_id、transmission_id、timestamp排序,得到符合要求的结果。
内容的提问来源于stack exchange,提问作者Shotey
相关产品推荐
相关产品推荐

