[英]Rows to Columns with iSeries DB2 SQL
我有一個簡單的數據表,如下所示:
col_1
==========
haddock
cod
hake
mackerel
tench
sprat
dace
rudd
pike
gudgeon
....
我想選擇數據,以便我可以在 5 列中輸出它:
col_1 col_2 col_3 col_4 col_5
======== ======== ======== ======== ========
haddock cod hake mackerel tench
sprat dace rudd pike gudgeon
...
有沒有很好的方法來做到這一點? NB iSeries DB2 SQL
為了說明發生了什么,我將使用“通用表表達式”將其分解為小階段 a,b,c,..,但這是一個 SELECT 語句
with a as
( select row_number() over(order by order of f) - 1 as nb,
col_1 as fish
from fishtable as f
), b as
( select smallint(nb/5)+1 as outrow,
smallint(mod(nb),5)+1 as outcol,
col_1 as fish
from a
), c as
( select outrow,
(case when outcol=1 then fish else null end) as fish1,
(case when outcol=2 then fish else null end) as fish2,
(case when outcol=3 then fish else null end) as fish3,
(case when outcol=4 then fish else null end) as fish4,
(case when outcol=5 then fish else null end) as fish5
from b
)
select outrow,
max(fish1) col_1,
max(fish2) col_2,
max(fish3) col_3,
max(fish4) col_4,
max(fish5) col_5
from c
group by outrow
order by outrow
第一步給你一個中間結果
rn fish
====== ==========
0 haddock
1 cod
2 hake
3 mackerel
4 tench
5 sprat
6 dace
7 rudd
8 pike
9 gudgeon
下一步給出
outrow outcol fish
====== ====== ==========
1 1 haddock
1 2 cod
1 3 hake
1 4 mackerel
1 5 tench
2 1 sprat
2 2 dace
2 3 rudd
2 4 pike
2 5 gudgeon
然后我們根據列號將值分散到單獨的列中
outrow fish1 fish2 fish3 fish4 fish5
====== ======== ======== ======== ======== ========
1 haddock
1 cod
1 hake
1 mackerel
1 tench
2 sprat
2 dace
2 rudd
2 pike
2 gudgeon
最后一步按 outrow 編號將行擠壓在一起
outrow col_1 col_2 col_3 col_4 col_5
====== ======== ======== ======== ======== ========
1 haddock cod hake mackerel tench
2 sprat dace rudd pike gudgeon
當然,該查詢的編寫方式似乎相當漫長。 我使用我構建的不同名字的表格對其進行了更大規模的測試。 然后我壓縮了我的語法。
select max(case when mod(rn,5)=0 then fname else null end) fname1
,max(case when mod(rn,5)=1 then fname else null end) fname2
,max(case when mod(rn,5)=2 then fname else null end) fname3
,max(case when mod(rn,5)=3 then fname else null end) fname4
,max(case when mod(rn,5)=4 then fname else null end) fname5
from (select fname, row_number() over(order by order of f)-1 as rn
from firstnames f
) as a
group by int(rn/5)
order by int(rn/5)
你真的想要單獨的 COLUMNS 還是你只是想讓數據成為包含五行值的單列。 如果您想要后者,請嘗試以下操作:
SELECT GROUP_CONCAT( a.col_1 SEPARATOR ' ' )
FROM (SELECT ( (@ROWNUM := CASE WHEN @ROWNUM IS NULL THEN 0 ELSE @ROWNUM + 1 END) DIV 5 ) AS group_num, col_1
FROM your_table) a
GROUP BY a.group_num;
如果你想要前者,比如:
SELECT GROUP_CONCAT( CASE WHEN a.row_num MOD 5 = 0 THEN a.col_1 ELSE '' END SEPARATOR '' ) AS col_1
,GROUP_CONCAT( CASE WHEN a.row_num MOD 5 = 1 THEN a.col_1 ELSE '' END SEPARATOR '' ) AS col_2
,GROUP_CONCAT( CASE WHEN a.row_num MOD 5 = 2 THEN a.col_1 ELSE '' END SEPARATOR '' ) AS col_3
,GROUP_CONCAT( CASE WHEN a.row_num MOD 5 = 3 THEN a.col_1 ELSE '' END SEPARATOR '' ) AS col_4
,GROUP_CONCAT( CASE WHEN a.row_num MOD 5 = 4 THEN a.col_1 ELSE '' END SEPARATOR '' ) AS col_5
FROM (SELECT @ROWNUM := CASE WHEN @ROWNUM IS NULL THEN 0 ELSE @ROWNUM + 1 END AS row_num, col_1
FROM your_table) a
GROUP BY a.row_num DIV 5;
請參閱http://sqlfiddle.com/#!2/7dc42/9 上的SQLFiddle
抱歉,剛剛注意到您正在尋找 iSeries DB2 SQL(不是 MySQL)的解決方案。 DB2 需要不同的解決方案。
如果你有可用的 DB2 LISTAGG 函數,你可以嘗試類似的東西(抱歉沒有辦法測試它,所以它可能不完美):
SELECT LISTAGG( CASE WHEN MOD(a.row_num, 5) = 0 THEN a.col_1 ELSE '' END, '' ) AS col_1
,LISTAGG( CASE WHEN MOD(a.row_num, 5) = 1 THEN a.col_1 ELSE '' END, '' ) AS col_2
,LISTAGG( CASE WHEN MOD(a.row_num, 5) = 2 THEN a.col_1 ELSE '' END, '' ) AS col_3
,LISTAGG( CASE WHEN MOD(a.row_num, 5) = 3 THEN a.col_1 ELSE '' END, '' ) AS col_4
,LISTAGG( CASE WHEN MOD(a.row_num, 5) = 4 THEN a.col_1 ELSE '' END, '' ) AS col_5
FROM (SELECT ROW_NUMBER() AS row_num, col_1
FROM your_table) a
GROUP BY INT(a.row_num / 5);
筆記:
1) 有使用 LISTAGG 的替代方法(如 XMLAGG)。 在此論壇中搜索 DB2 GROUP_CONCAT 替代方案。 有很多例子。
2) 如果沒有可用的 ROW_NUMBER(),可以在 DB2 中使用遞歸 SQL 進行模擬。
我有一個似乎有效但不是很優雅的解決方案:
with tab1 as ( select col_1 as col_1 from my_table a where mod(rrn(a), 5) = 1 ),
with tab2 as ( select col_1 as col_1 from my_table a where mod(rrn(a), 5) = 2 ),
with tab3 as ( select col_1 as col_1 from my_table a where mod(rrn(a), 5) = 3 ),
with tab4 as ( select col_1 as col_1 from my_table a where mod(rrn(a), 5) = 4 ),
with tab5 as ( select col_1 as col_1 from my_table a where mod(rrn(a), 5) = 0 )
select tab1.col_1 as col_1,
tab2.col_1 as col_2,
tab3.col_1 as col_3,
tab4.col_1 as col_4,
tab5.col_1 as col_5
from tab1 LEFT JOIN tab2 on rrn(tab1) + 1 = rrn(tab2)
LEFT JOIN tab3 on rrn(tab2) + 1 = rrn(tab3)
LEFT JOIN tab4 on rrn(tab3) + 1 = rrn(tab4)
LEFT JOIN tab5 on rrn(tab4) + 1 = rrn(tab5)
IBMi SQL 參考 (v7r3) 中的示例:
生成按字母順序排列的逗號分隔名稱列表,按部門分組:
SELECT workdept, LISTAGG(lastname, ', ') WITHIN GROUP(ORDER BY lastname) AS員工 FROM emp GROUP BY workdept;
生成以下結果:
工作部員工
A00 HAAS、HEMMINGER、LUCCHESSI、奧康奈爾、奧蘭多
B01 湯普森
C01 關、納茲、尼科爾斯、昆塔納……
干凈,工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.