原始資料:學生成績明細表
| name | km | cj |
|---|---|---|
| 張三 | 語文 | 80 |
| 張三 | 數學 | 86 |
| 張三 | 英語 | 75 |
| 李四 | 語文 | 78 |
| 李四 | 數學 | 85 |
| 李四 | 英語 | 78 |
目標結果:
| 姓名 | 語文 | 數學 | 英語 |
|---|---|---|---|
| 張三 | 80 | 86 | 75 |
| 李四 | 78 | 85 | 78 |
SELECT name,
SUM(CASE km WHEN '數學' THEN cj END) AS 數學,
SUM(CASE km WHEN '英語' THEN cj END) AS 英語,
SUM(CASE km WHEN '語文' THEN cj END) AS 語文
FROM test
GROUP BY name;
DECLARE @sql NVARCHAR(MAX) = N'SELECT name';
SELECT @sql += N', SUM(CASE km WHEN ' + QUOTENAME(km, '''') + N' THEN cj END) AS ' + QUOTENAME(km)
FROM (SELECT DISTINCT km FROM test) AS t;
SET @sql += N' FROM test GROUP BY name';
PRINT @sql; -- 除錯用
EXEC sp_executesql @sql;
原始資料:
| cardno | sex | age |
|---|---|---|
| 1 | 男 | 12 |
| 2 | 男 | 10 |
| 3 | 女 | 14 |
| 4 | 女 | 18 |
| 5 | 男 | 20 |
目標:依性別計算平均年齡,呈現為欄位
| 男 | 女 |
|---|---|
| 14 | 16 |
DECLARE @sql NVARCHAR(MAX) = N'SELECT ';
SELECT @sql += N'SUM(CASE sex WHEN ' + QUOTENAME(sex, '''') + N' THEN avg_age END) AS ' + QUOTENAME(sex) + N','
FROM (SELECT sex, AVG(age) AS avg_age FROM t GROUP BY sex) AS a;
SET @sql = LEFT(@sql, LEN(@sql) - 1) + N' FROM (SELECT sex, AVG(age) AS avg_age FROM t GROUP BY sex) AS a';
EXEC sp_executesql @sql;
原始資料:寬表(一列多欄位)
CREATE TABLE t1 (a INT, b INT, c INT, d INT, e INT, f INT, g INT);
INSERT INTO t1 VALUES (1,2,3,4,5,6,7);
目標:轉為長表(每欄位一列)
| col_name | col_value |
|---|---|
| a | 1 |
| b | 2 |
| c | 3 |
| d | 4 |
| e | 5 |
| f | 6 |
| g | 7 |
SELECT 'a' AS col_name, a AS col_value FROM t1 UNION ALL
SELECT 'b', b FROM t1 UNION ALL
SELECT 'c', c FROM t1 UNION ALL
SELECT 'd', d FROM t1 UNION ALL
SELECT 'e', e FROM t1 UNION ALL
SELECT 'f', f FROM t1 UNION ALL
SELECT 'g', g FROM t1;
SELECT col_name, col_value
FROM t1
UNPIVOT (col_value FOR col_name IN (a,b,c,d,e,f,g)) AS u;
DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX);
SELECT @cols = STRING_AGG(QUOTENAME(name), ',') -- SQL 2017+
FROM sys.columns
WHERE object_id = OBJECT_ID('t1');
SET @sql = N'SELECT col_name, col_value FROM t1 UNPIVOT (col_value FOR col_name IN (' + @cols + N')) AS u';
EXEC sp_executesql @sql;
若需同時依「年級」與「科目」交叉顯示「平均分數」與「及格率」,可結合 GROUPING SETS、CUBE、ROLLUP 或多層 CASE 運算,或使用報表工具(SSRS、Power BI)呈現更靈活。
QUOTENAME、sp_executesql 參數化,避免直接拼接字串。