2017-03-02 47 views
0

我有一個表(在PostgreSQL數據庫中),其中一些id的多行有一些值,而有些則爲null。 表看起來像這樣(例如玩具):壓扁那些列爲NULL的行

PSQL:test/[email protected][local]=> SELECT * FROM t1; 
id | x | y | z 
----+-----+-----+---- 
    1 |  | 200 | 
    1 | 100 |  | 42 
    2 | 45 |  |  
(3 rows) 

更重要的是:我可以保證,有對同一編號行,其中同一領域具有非NULL值。 在上面的例子中,不會有任何其他行ID爲1.

我期待聚合每個id的所有值,擠壓非空的。也就是說,將其改造成這樣的

id | x | y | z 
----+-----+-----+---- 
    1 | 100 | 200 | 42 
    2 | 45 |  |  
(2 rows) 

我得到的最接近是使用的COALESCE(field1, '') || COALESCE(field2, '') || ...級聯但結果不是我想要的:

PSQL:test/[email protected][local]=> SELECT id, COALESCE(x::TEXT || ',' , '') || COALESCE(y::TEXT || ',', '') || COALESCE(z::TEXT || ',', '') AS agg FROM t1 GROUP BY id, agg; 
id | agg 
----+--------- 
    1 | 100,42, 
    1 | 200, 
    2 | 45,  
(3 rows) 

不知道如何解決這個問題問題?

回答

3

只需使用聚集,例如, min() - 它會忽略空值:

select id, 
     min(x) as x, 
     min(y) as y, 
     min(z) as z 
from t1 
group by id; 

這依賴於你的要求說:「我可以保證,有對同一編號行,其中同一領域具有非NULL值」 - 否則這當然會返回錯誤的信息。


另外,您可以使用array_agg()把所有的值到一個數組,以防萬一你也許每個ID獲得多個值。

select id, 
     array_agg(x) filter (where x is not null), 
     array_agg(y) filter (where y is not null), 
     array_agg(z) filter (where z is not null) 
from t1 
group by id; 
+0

感謝提供無論是「分」的解決方案,它依賴於我的要求,也是通用的解決方案:但是string_agg()所以你需要應用一個過濾器不忽略空值。這兩個奇蹟! – Jir