我正在尝试使用full outer join
将多个表连接在一起,它接近正确的结果但由于join子句有一些重复的行。我有几个包含id,date,value列的表。我希望得到一个表,每个id都有一行,日期对包含每个表的所有值。
Here is a SQLFiddle if you want to play with it.
这是我到目前为止所得到的:
SELECT
COALESCE(T1.ID, T2.ID, T3.ID, t4.id) AS ID,
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt) AS DATE,
T1.AMT1, T2.AMT2, T3.AMT3, t4.AMT4
FROM T1
FULL OUTER JOIN T2
ON
T2.id = T1.id
AND T2.event_dt = T1.event_dt
FULL OUTER JOIN T3
ON
T3.id = T1.id
AND T3.event_dt = T1.event_dt
FULL OUTER JOIN T4
ON
T4.id = T1.id
AND T4.event_dt = T1.event_dt
ORDER BY ID, DATE
这几乎可以工作,但是我得到了一些重复的行,例如T4有一个ID,event_dt对不在T1中(因为这就是我正在加入的东西)。例如,我会得到类似的东西:
1 April, 06 2012 00:00:00+0000 (null) 2 (null) (null)
1 April, 06 2012 00:00:00+0000 (null) (null) (null) 4
1 April, 06 2012 00:00:00+0000 (null) (null) 3 (null)
When I'm looking to get:
1 April, 06 2012 00:00:00+0000 (null) 2 3 4
有没有办法将这些行压平/合并在一起,还是有更好的方法来解决这个问题?
答案 0 :(得分:3)
您始终可以在amount
列周围使用聚合:
SELECT
COALESCE(T1.ID, T2.ID, T3.ID, t4.id) AS ID,
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt) AS DATE,
max(coalesce(T1.AMT1, 0)) AMT1, -- use coalesce to replace the null with zero
max(coalesce(T2.AMT2, 0)) AMT2,
max(coalesce(T3.AMT3, 0)) AMT3,
max(coalesce(t4.AMT4, 0)) AMT4
FROM T1
FULL OUTER JOIN T2
ON T2.id = T1.id
AND T2.event_dt = T1.event_dt
FULL OUTER JOIN T3
ON T3.id = T1.id
AND T3.event_dt = T1.event_dt
FULL OUTER JOIN T4
ON T4.id = T1.id
AND T4.event_dt = T1.event_dt
group by COALESCE(T1.ID, T2.ID, T3.ID, t4.id),
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt)
ORDER BY ID, DATE;
请参阅Demo
答案 1 :(得分:3)
我认为你加入citeria根本不是你真正想要的东西。这个应该做的伎俩:
SELECT
COALESCE(T1.ID, T2.ID, T3.ID, t4.id) AS ID,
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt) AS DATE,
T1.AMT1, T2.AMT2, T3.AMT3, t4.AMT4
FROM T1
FULL OUTER JOIN T2
ON
T2.id = T1.id
AND T2.event_dt = T1.event_dt
FULL OUTER JOIN T3
ON
T3.id = coalesce(T1.id, T2.id)
AND T3.event_dt = coalesce(T1.event_dt, T2.event_dt)
FULL OUTER JOIN T4
ON
T4.id = coalesce(T1.id, T2.id, T3.id)
AND T4.event_dt = coalesce(T1.event_dt, T2.event_dt, T3.event_dt)
ORDER BY ID, DATE
SQL-Fiddle here为您提供2012-04-06所需的输出。
答案 2 :(得分:2)
陷阱为NULL,用零重新移动它们,然后在每列中找到MAX值。
SELECT
COALESCE(T1.ID, T2.ID, T3.ID, t4.id) AS ID,
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt) AS DATE,
max( coalesce(T1.AMT1,0)) as amt1
, max( coalesce(T2.AMT2,0)) as amt2
, max( coalesce(T3.AMT3,0)) as amt3
, max( coalesce(t4.AMT4,0)) as amt4
FROM T1
FULL OUTER JOIN T2
ON
T2.id = T1.id
AND T2.event_dt = T1.event_dt
FULL OUTER JOIN T3
ON
T3.id = T1.id
AND T3.event_dt = T1.event_dt
FULL OUTER JOIN T4
ON
T4.id = T1.id
AND T4.event_dt = T1.event_dt
group by COALESCE(T1.ID, T2.ID, T3.ID, t4.id),
COALESCE(T1.event_dt, T2.event_dt, T3.event_dt, t4.event_dt)
ORDER BY ID, DATE
这是Fiddle
答案 3 :(得分:1)
(假设OP想要一个完全对称的外部4连接)
WITH four AS (
SELECT id, event_dt FROM t1
UNION
SELECT id, event_dt FROM t2
UNION
SELECT id, event_dt FROM t3
UNION
SELECT id, event_dt FROM t4
)
SELECT f.id, f.event_dt
, t1.amt1
, t2.amt2
, t3.amt3
, t4.amt4
FROM four f
LEFT JOIN t1 ON t1.id = f.id AND t1.event_dt = f.event_dt
LEFT JOIN t2 ON t2.id = f.id AND t2.event_dt = f.event_dt
LEFT JOIN t3 ON t3.id = f.id AND t3.event_dt = f.event_dt
LEFT JOIN t4 ON t4.id = f.id AND t4.event_dt = f.event_dt
ORDER BY id, event_dt
;
结果:
id | event_dt | amt1 | amt2 | amt3 | amt4
----+------------+------+------+------+------
1 | 2012-04-01 | 1 | | |
1 | 2012-04-02 | 1 | | 3 |
1 | 2012-04-03 | 1 | | 3 |
1 | 2012-04-06 | | 2 | 3 | 4
1 | 2012-04-07 | | 2 | |
2 | 2012-04-01 | 40 | | |
2 | 2012-04-02 | | | 3 |
2 | 2012-04-03 | | | 3 |
2 | 2012-04-04 | 40 | | |
(9 rows)
BTW:在UNION
四之后,LEFT JOIN
将与FULL JOIN
s相同(联合四已经拥有所有可能的{id,event_dt}对)