1. 程式人生 > >[資料庫] SQL查詢語句錶行列轉換及一行資料轉換成兩列

[資料庫] SQL查詢語句錶行列轉換及一行資料轉換成兩列

本文主要講述了SQL查詢語句表之間的行列轉換,同時也包括如何將一行資料轉換成兩列資料的方法、子查詢的應用、decode函式的用法。希望文章對你有所幫助~
  • 1.建立資料庫表及插入資料
  • 2.子查詢統計不同性質的學生總數
  • 3.一行資料轉換成兩列資料 union all
  • 4.錶行列資料轉換(錶轉置)

1.建立資料庫表及插入資料

建立資料庫、建立學生表並設定主鍵、插入資料程式碼如下:

--建立資料庫  
create database StudentMS  
  
--使用資料庫  
use StudentMS  

--建立學生表 (屬性:姓名、學號(pk)、學院、出生日期、性別、籍貫)  
create table xs  
(  
    name varchar(10) not null,  
    id varchar(10) not null,  
    xy varchar(10),  
    birthday datetime,  
    xb char(2),  
    jg varchar(8)  
)  

--建立學生表主鍵:學號  
alter table xs  
    add constraint  
pk_xs primary key(id)  

--插入資料
insert into xs   
    (id, name, xb, birthday, xy, jg)   
values('1160001', '劉備', '男', '1991-11-5', '軟體學院', '河北省');   
輸出資料如下圖所示:

2.子查詢統計不同性質的學生總數

使用子查詢統計不同學院總人數、不同性別總人數和河北/河南學生總人數。

--子查詢統計人數  
select a.a_num as 軟院人數, b.b_num as 計院人數, c.c_num as 自動化人數,   
       d.d_num as 男生人數, e.e_num as 女生人數, f.f_num as 河北河南人數  
from  
(select count(*) as a_num from xs where xy='軟體學院') a,  
(select count(*) as b_num from xs where xy='計算機學院') b,  
(select count(*) as c_num from xs where xy='自動化學院') c,  
(select count(*) as d_num from xs where xb='男') d,  
(select count(*) as e_num from xs where xb='女') e,  
(select count(*) as f_num from xs where jg in ('河北省','河南省')) f;  
輸出結果:
PS:若中文漢字太長報錯,則需引用雙引號。如:select num as "專案(文化學術講座)"


3.一行資料轉換成兩列資料

這時,專案SQL語句的需要是顯示成兩列如下圖所示:

其實簡單編寫SQL語句,前端再處理這些資料更加方便,當然SQL也是能處理的。
當時走進了一個誤區,認為"軟體人數"是select中as自定義的一行資料的屬性,如何顯示在表中呢?當時是通過Oracle方法decode自定義顯示的,其實直接輸出,union all取代子查詢即可。當然union all其它表也可以繼續新增。
select '軟院人數' as "統計類別", count(*) as "數量" from xs where xy='軟體學院'
union all
select '計院人數', count(*) from xs where xy='計算機學院'
union all
select '自動化人數', count(*) from xs where xy='自動化學院'
union all
select '男生人數', count(*) from xs where xb='男'
union all
select '女生人數', count(*) from xs where xb='女'
union all
select '河北河南人數', count(*) from xs where jg in ('河北省','河南省');

這裡我簡單給大家回顧下UNION ALL方法:(參考:MIN飛翔部落格)
UNION:
        (1) 其目的是將兩個SQL語句的結果合併起來;
        (2) 它的一個限制是兩個SQL語句所產生的欄位需要是同樣的資料種類;
        (3) UNION只是將兩個結果聯結起來一起顯示,並不是聯結兩個表;
        (4) UNION在進行錶鏈接後會篩選掉重複的記錄。

UNION ALL:
        (1) 這個指令的目的也是要將兩個 SQL 語句的結果合併在一起;
        (2) UNION ALL 和 UNION 不同之處在於 UNION ALL 會將每一個符合條件的資料都列出來,無論資料值有無重複;
        (3) UNION ALL只是簡單的將兩個結果合併後就返回。這樣,如果返回的兩個結果集中有重複的資料,那麼返回的結果集就會包含重複的資料了。

從效率上說,sql union all的執行效率要比sql union效率要高很多,這是因為使用sql union需要進行排重,而sql union All 是不需要排重的,這一點非常重要,因為對於一些單純地使用分表來提高效率的查詢,完全可以使用sql union All。

補充:(摒棄的程式碼)
當時使用decode函式,如果KWHD_WH_XZ='校級',則輸出自定義值'校級總數',否則輸出原始值;同時通過group by獲取該列所有值,sum(decode(t.KWHD_WH_XZ,'校級',1,0)計算校級的個數。
select whxs1.num1 as 專案名稱,  whxs2.num2 as 數量
from
(select decode(KWHD_WH_XZ, '校級', '校級總數', KWHD_WH_XZ) as num1
from T_WSTB_KWHD_1 t
where KWHD_WH_XZ='校級'
group by KWHD_WH_XZ) whxs1,
(select sum(decode(t.KWHD_WH_XZ,'校級',1,0)) as num2
from T_WSTB_KWHD_1 t
where KWHD_WH_XZ='校級'
group by KWHD_WH_XZ ) whxs2;
輸出如下,但是再新增一行資料如何實現呢?所以還是推薦UNION ALL。



4.錶行列資料轉換(錶轉置)

SQL語句如下:
select country, sum(case when type='A' then money end) as A,
sum(case when type='B' then money end) as B,
sum(case when type='C' then money end) as C
from table1
group by country


decode(條件,值1,結果1,值2,結果2,值3,結果3,... 值n,結果n,預設值)

函式類比:
IF 條件=值1 THEN
    RETURN(結果1)
ELSIF 條件=值2 THEN
    RETURN(結果2)
    ......
ELSIF 條件=值n THEN
    RETURN(結果n)
ELSE
    RETURN(預設值)
END IF
舉個例子如下:

SQL語句如下,其中sum(decode(t.result,'勝',1,0))表示result欄位如果值為“勝”,則decode的結果值為1,否則取預設值0,最後sum統計加和。

select
name as 姓名,sum(decode(t.result,'勝',1,0)) as 勝,sum(decode(t.result,'負',1,0)) as 負
from t_result t
group by name
order by 勝 desc,負 asc

最後希望文章對你有所幫助,其實SQL語句中還是有很多非常高深的變化,目前只窺得一二啊!fighting...O(∩_∩)O