在數據庫報表查詢時事實表中的數據很多情況下沒有直接反映最終報表需求的格式,其中很典型的就是要把多行的數據轉換成列的形式顯示,舉例如下:
事實表T_Score(學生成績表):
CREATE TABLE "DB2ADMIN"."T_SCORE" (
"NAME" VARCHAR(20) ,
"SUBJECT" VARCHAR(20) ,
"SCORE" INTEGER ) ;
示例數據:
Mary Chinese 90
Mary English 84
Mary Maths 79
Tom Chinese 86
Tom English 93
Tom Maths 89
但是報表需求:
NAME Chinese English Maths
Mary 90 84 79
Tom 86 93 89
SQL實現:
select name,
sum(decode(subject,'Chinese',score)) as Chinese,
sum(decode(subject,'English',score)) as English,
sum(decode(subject,'Maths',score)) as Maths
from t_score group by name;
另外還有一種需求是希望把多行的數據合併到一列中,可以利用oracle的樹結構查詢獲得(connect by 語句):
select sys_connect_by_path(r_name,'|'),level LV from
(select r_name,row_number() over (order by id_stock desc) rn
from t_stocks_fact) where level>3 connect by rn=prior rn+1;
至於列轉爲行則可以用union all來實現,以T_Score_Row爲例,
select name, 'Chinese' as subject, chinese from T_Score_Row
union all
select name, 'English' as subject, english from T_Score_Row
union all
select name, 'Maths' as subject, maths from T_Score_Row
以下SQL是上面行轉列過程的逆操作而已。
select * from (
select name, 'Chinese' as subject, chinese from (
select name,
sum(decode(subject,'Chinese',score)) as Chinese,
sum(decode(subject,'English',score)) as English,
sum(decode(subject,'Maths',score)) as Maths
from t_score group by name)
union all
select name, 'English' as subject, english from (
select name,
sum(decode(subject,'Chinese',score)) as Chinese,
sum(decode(subject,'English',score)) as English,
sum(decode(subject,'Maths',score)) as Maths
from t_score group by name
)
union all
select name, 'Maths' as subject, maths from (
select name,
sum(decode(subject,'Chinese',score)) as Chinese,
sum(decode(subject,'English',score)) as English,
sum(decode(subject,'Maths',score)) as Maths
from t_score group by name
)
) order by name