DB2 行轉列
----start
在網上看到這樣一個問題:(問題地址:http://www.mydb2.cn/bbs/read.php?tid=1297&page=e&#a)
- 班級 科目 分數
- 1 語文 8800
- 1 數學 8420
- 1 英語 7812
- ……
- 2 語文 8715
- 2 數學 8511
- 2 英語 8512
- ……
- 要求轉換成下面這樣的結果
- 班級 語文 數學 英語
- 1 8800 8420 7812
- 2 8715 8511 8512
這是一個非常經典的 4屬性的表設計模式,顧名思義,這樣的表一般有四列,分別是:entity_id, attribute_name,attribute_type, attribute_value ,這樣的設計使我們添加字段非常容易,如:我們想添加一個物理成績是非常簡單的,我們只要向表中插入一條記錄即可。但是,這樣的設計有一個非常嚴重的問題,那就是:查詢難度增加,查詢效率非常差。
要想實現上面的查詢有一個原則,那就是:通過case語句創造虛擬字段,使結果集成為二維數組,然后應用聚合函數返回單一記錄。怎么樣?不理解,仔細看看下面的圖和分析下面的語句你就理解了。
- create table score
- (
- banji integer,
- kemu varchar(10),
- fengshu integer
- )
- go
- insert into score values
- (1, '語文', 8800),
- (1, '數學', 8420),
- (1, '英語', 7812),
- (2, '語文', 8715),
- (2, '數學', 8511),
- (2, '英語', 8512)
- go
- select banji,
- max(yuwen) 語文,
- max(shuxue) 數學,
- max(yingyu) 英語
- from
- (select banji,
- case kemu
- when '語文' then fengshu
- else 0
- end yuwen,
- case kemu
- when '數學' then fengshu
- else 0
- end shuxue,
- case kemu
- when '英語' then fengshu
- else 0
- end yingyu
- from score
- ) as inner
- group by inner.banji
- order by 1
- go
你可能正在感嘆,這樣的解決方案是多么的巧妙,可惜不是我想出來的,在這里,我也不敢把大師的思想據為己有,以上思想來自<SQL語言藝術>的第11章,想了解更全面的信息,大家可以參考。
---更多參見:DB2 SQL 精萃
----聲明:轉載請注明出處。
----last updated on 2009.12.20
----written by ShangBo on 2009.12.16
----end
DB2 列轉行
行轉列
給出下面的數據:
CREATE TABLE Sales (Year INT, Quarter INT, Results INT)
YEAR QUARTER RESULTS
----------- ----------- -----------
2004 1 20
2004 2 30
2004 3 15
2004 4 10
2005 1 18
2005 2 40
2005 3 12
2005 4 27
想要的到結果:
YEAR Q1 Q2 Q3 Q4
----------- ----------- ----------- ----------- -----------
2004 20 30 15 10
2005 18 40 12 27
這個SQL就可解決這個問題:
SELECT Year,
MAX(CASE WHEN Quarter = 1
THEN Results END) AS Q1,
MAX(CASE WHEN Quarter = 2
THEN Results END) AS Q2,
MAX(CASE WHEN Quarter = 3
THEN Results END) AS Q3,
MAX(CASE WHEN Quarter = 4
THEN Results END) AS Q4
FROM Sales
GROUP BY Year
解釋一下為什么要加max的原因,因為不加max的話結果會是這樣:
YEAR Q1 Q2 Q3 Q4
----------- ----------- ----------- ----------- -----------
2004 20 - - -
2004 - 30 - -
2004 - - 15 -
2004 - - - 10
2005 18 - - -
2005 - 40 - -
2005 - - 12 -
2005 - - - 27
列轉行
給出下面數據
CREATE TABLE SalesAgg
( year INTEGER,
q1 INTEGER,
q2 INTEGER,
q3 INTEGER,
q4 INTEGER );
YEAR Q1 Q2 Q3 Q4
----------- ----------- ----------- ----------- -----------
2004 20 30 15 10
2005 18 40 12 27
想要的結果
YEAR QUARTER RESULTS
----------- ----------- -----------
2004 1 20
2004 2 30
2004 3 15
2004 4 10
2005 1 18
2005 2 40
2005 3 12
2005 4 27
這個SQL就可以實現:
SELECT S.Year, Q.Quarter, Q.Results
FROM SalesAgg AS S,
TABLE (VALUES(1, S.q1),
(2, S.q2),
(3, S.q3),
(4, S.q4))
AS Q(Quarter, Results);
每個values中對應列的數據類型必須相同,值可以任意,如1,2,3,4都是整形
下面解釋一下執行的過程:
核心是用table函數創建了一個表,這個表是用value實現的多行表,value實現虛表的例子:
db2 => select * from (values (1,2),(2,3)) as t1(col1,col2)
COL1 COL2
----------- -----------
1 2
2 3
2 條記錄已選擇。
db2 => select * from (values 1) as a
1
-----------
1
1 條記錄已選擇。
所不同的是這里跟from子句中的一個表產生了關系,取出了表中的一列作為數據.