| Name | Subject | Result |
|---|---|---|
| 張三 | 語文 | 85 |
| 張三 | 數學 | 92 |
| 張三 | 英語 | 78 |
| 李四 | 語文 | 90 |
| 李四 | 數學 | 88 |
| 李四 | 英語 | 95 |
SELECT name,
DECODE(subject, '語文', 1, '數學', 2, '英語', 3) AS subject_code
FROM results;
-- 簡單 CASE
SELECT name,
CASE subject
WHEN '語文' THEN 1
WHEN '數學' THEN 2
WHEN '英語' THEN 3
END AS subject_code
FROM results;
-- 搜尋 CASE(更靈活,支援複合條件)
SELECT name,
CASE
WHEN subject = '語文' THEN 1
WHEN subject = '數學' THEN 2
WHEN subject = '英語' THEN 3
END AS subject_code
FROM results;
結論:DECODE 為 Oracle 專有,簡潔但功能受限;CASE 為 ANSI 標準,跨平台、支援複雜邏輯、可巢狀,**推薦統一使用 CASE**。
SELECT name,
SUM(DECODE(subject, '語文', result, 0)) AS 語文,
SUM(DECODE(subject, '數學', result, 0)) AS 數學,
SUM(DECODE(subject, '英語', result, 0)) AS 英語
FROM results
GROUP BY name;
SELECT name,
SUM(CASE WHEN subject = '語文' THEN result ELSE 0 END) AS 語文,
SUM(CASE WHEN subject = '數學' THEN result ELSE 0 END) AS 數學,
SUM(CASE WHEN subject = '英語' THEN result ELSE 0 END) AS 英語
FROM results
GROUP BY name;
| Name | 語文 | 數學 | 英語 |
|---|---|---|---|
| 張三 | 85 | 92 | 78 |
| 李四 | 90 | 88 | 95 |
-- Oracle
SELECT name,
DECODE(subject, '語文', result, 0) AS 語文,
DECODE(subject, '數學', result, 0) AS 數學,
DECODE(subject, '英語', result, 0) AS 英語
FROM results;
-- 標準 CASE
SELECT name,
CASE WHEN subject = '語文' THEN result ELSE 0 END AS 語文,
CASE WHEN subject = '數學' THEN result ELSE 0 END AS 數學,
CASE WHEN subject = '英語' THEN result ELSE 0 END AS 英語
FROM results;
中間結果每列僅有一科有分數,其餘為 0,再經 SUM + GROUP BY 合併。
靜態 SQL 無法動態產生欄,需動態 SQL 或應用層組裝:
-- Oracle 11g+ PIVOT 语法(靜態)
SELECT * FROM (
SELECT name, subject, result FROM results
)
PIVOT (
SUM(result) FOR subject IN ('語文' AS 語文, '數學' AS 數學, '英語' AS 英語)
);
-- 動態 PL/SQL 產生 PIVOT SQL
DECLARE
v_sql VARCHAR2(4000);
v_cols VARCHAR2(4000);
BEGIN
SELECT LISTAGG('''' || subject || ''' AS ' || subject, ',') WITHIN GROUP (ORDER BY subject)
INTO v_cols FROM (SELECT DISTINCT subject FROM results);
v_sql := 'SELECT * FROM (SELECT name, subject, result FROM results) PIVOT (SUM(result) FOR subject IN (' || v_cols || '))';
EXECUTE IMMEDIATE v_sql;
END;
| 方案 | 優點 | 缺點 | 建議 |
|---|---|---|---|
| CASE + SUM | 標準、跨平台、最佳化器熟悉 | 靜態欄位需硬編碼 | 首選方案 |
| DECODE + SUM | Oracle 簡潔 | 非標準、功能受限 | 僅限 Oracle 簡易報表 |
| PIVOT / UNPIVOT (11g+) | 語法清晰、最佳化器專門處理 | Oracle 專有、動態仍需動態 SQL | 固定樞紐報表優先 |
| 應用層組裝 | 完全動態、資料庫壓力小 | 網路傳輸量大、邏輯分散 | 欄位極動態、前端報表工具 |
SELECT name, [語文], [數學], [英語]
FROM (
SELECT name, subject, result FROM results
) src
PIVOT (
SUM(result) FOR subject IN ([語文], [數學], [英語])
) pvt;