SELECT id || username AS str FROM app_user; SELECT CONCAT(id, username) AS str FROM app_user;
SUBSTR + INSTR 定位分隔符REGEXP_SUBSTR 正則擷取(11g+ 推薦)UNION ALL 手動展開WM_CONCAT(col) 以逗號預設分隔,將群組內多行合併為單一字串。
CREATE TABLE test(id NUMBER, name VARCHAR2(20)); INSERT INTO test VALUES(1,'a'); INSERT INTO test VALUES(1,'b'); INSERT INTO test VALUES(1,'c'); INSERT INTO test VALUES(2,'d'); INSERT INTO test VALUES(2,'e');
| 需求 | SQL | 結果 |
|---|---|---|
| 預設逗號分隔 | SELECT WM_CONCAT(name) FROM test; | a,b,c,d,e |
| 自訂分隔符 | | SELECT REPLACE(WM_CONCAT(name),',','|') FROM test; | a|b|c|d|e |
| 依 ID 分組合併 | SELECT id, WM_CONCAT(name) FROM test GROUP BY id; | 1:a,b,c / 2:d,e |
-- MAX + DECODE
SELECT id,
MAX(DECODE(rn,1,name))||
MAX(DECODE(rn,2,','||name))||
MAX(DECODE(rn,3,','||name)) str
FROM (SELECT id,name,ROW_NUMBER() OVER(PARTITION BY id ORDER BY name) rn FROM test)
GROUP BY id;
-- SYS_CONNECT_BY_PATH
SELECT id, SUBSTR(SYS_CONNECT_BY_PATH(name,','),2) str
FROM (SELECT id,name,ROW_NUMBER() OVER(PARTITION BY id ORDER BY name) rn FROM test)
START WITH rn=1 CONNECT BY rn=PRIOR rn+1 AND id=PRIOR id
GROUP BY id;
SELECT 'CREATE OR REPLACE VIEW v_app AS SELECT '||
WM_CONCAT(column_name)||' FROM app_user' sql_str
FROM user_tab_columns WHERE table_name='APP_USER';
測試資料:水果銷售記錄
CREATE TABLE demo(id INT, name VARCHAR2(20), nums INT); INSERT INTO demo VALUES(1,'蘋果',1000); INSERT INTO demo VALUES(2,'蘋果',2000); INSERT INTO demo VALUES(3,'蘋果',4000); INSERT INTO demo VALUES(4,'橘子',5000); INSERT INTO demo VALUES(5,'橘子',3000); INSERT INTO demo VALUES(6,'葡萄',3500); INSERT INTO demo VALUES(7,'芒果',4200); INSERT INTO demo VALUES(8,'芒果',5500);
語法:
SELECT * FROM (
SELECT name, nums FROM demo
) PIVOT (
SUM(nums) FOR name IN ('蘋果' AS 蘋果, '橘子' AS 橘子, '葡萄' AS 葡萄, '芒果' AS 芒果)
);
結果:單行顯示四種水果總銷量欄位。
等價傳統寫法(多子查詢聯結,效能較差)。
測試資料:寬表記錄季度銷售
CREATE TABLE fruit(id INT, name VARCHAR2(20), q1 INT, q2 INT, q3 INT, q4 INT); INSERT INTO fruit VALUES(1,'蘋果',1000,2000,3300,5000); INSERT INTO fruit VALUES(2,'橘子',3000,3000,3200,1500); INSERT INTO fruit VALUES(3,'香蕉',2500,3500,2200,2500); INSERT INTO fruit VALUES(4,'葡萄',1500,2500,1200,3500);
語法:
SELECT id, name, jidu, xiaoshou FROM fruit UNPIVOT (xiaoshou FOR jidu IN (q1, q2, q3, q4));
結果:每種水果拆解為 4 行,含季度與銷量欄位。
當 IN 列表值未知時,使用 PIVOT XML ... IN (ANY) 產生 XMLType 輸出,再由 XML 解析器處理。
SELECT * FROM ( SELECT name, nums AS "Purchase Frequency" FROM demo ) PIVOT XML (SUM(nums) FOR name IN (ANY));
PIVOT/UNPIVOT,語法清晰、效能優化、支援 XML 動態欄位。WM_CONCAT(非官方文件化)或 MAX+DECODE、SYS_CONNECT_BY_PATH 等標準寫法。WM_CONCAT 可能受 4000 位元組限制,考慮 LISTAGG (11gR2+) 或自定義聚合函數。