DB2行轉列、列轉行等操作


DB2 行轉列

----start

在網上看到這樣一個問題:(問題地址:http://www.mydb2.cn/bbs/read.php?tid=1297&page=e&#a

 

[c-sharp] view plain copy print ?
  1. 班級  科目   分數  
  2. 1     語文   8800  
  3. 1     數學   8420  
  4. 1     英語   7812  
  5. ……  
  6. 2     語文   8715  
  7. 2     數學   8511  
  8. 2     英語   8512  
  9. ……  
  10.    
  11.    
  12. 要求轉換成下面這樣的結果  
  13. 班級    語文    數學    英語  
  14. 1       8800    8420    7812  
  15. 2       8715    8511    8512  

這是一個非常經典的 4屬性的表設計模式,顧名思義,這樣的表一般有四列,分別是:entity_id, attribute_name,attribute_type, attribute_value ,這樣的設計使我們添加字段非常容易,如:我們想添加一個物理成績是非常簡單的,我們只要向表中插入一條記錄即可。但是,這樣的設計有一個非常嚴重的問題,那就是:查詢難度增加,查詢效率非常差。

要想實現上面的查詢有一個原則,那就是:通過case語句創造虛擬字段,使結果集成為二維數組,然后應用聚合函數返回單一記錄。怎么樣?不理解,仔細看看下面的圖和分析下面的語句你就理解了。

 

[c-sharp] view plain copy print ?
  1. create table score  
  2. (  
  3.     banji integer,  
  4.     kemu varchar(10),   
  5.     fengshu integer  
  6. )  
  7. go  
  8.    
  9. insert into score values  
  10. (1, '語文', 8800),  
  11. (1, '數學', 8420),  
  12. (1, '英語', 7812),  
  13. (2, '語文', 8715),  
  14. (2, '數學', 8511),  
  15. (2, '英語', 8512)  
  16. go  
  17.    
  18. select banji,  
  19.        max(yuwen)        語文,  
  20.        max(shuxue)       數學,  
  21.        max(yingyu)       英語  
  22. from    
  23.      (select  banji,  
  24.               case kemu  
  25.                when '語文' then fengshu  
  26.                else 0  
  27.              end                         yuwen,  
  28.              case kemu  
  29.                when '數學' then fengshu  
  30.                else 0  
  31.              end                         shuxue,  
  32.              case kemu  
  33.                when '英語' then fengshu  
  34.                else 0  
  35.              end                         yingyu  
  36.       from score  
  37.       ) as inner  
  38. group by inner.banji  
  39. order by 1  
  40. 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子句中的一個表產生了關系,取出了表中的一列作為數據.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM