在平常的工作中或者面試中,我們可能有遇到過數據庫的縱橫表的轉換問題。今天我們就來討論下。
1.創建表
首先我們來創建一張表。
sql語句:
1 -- 1. 創建數據表 2 if OBJECT_ID ( ' Score ' ) is not null drop table Score 3 4 create table Score 5 ( 6 姓名 nvarchar ( 128 ), 7 課程 nvarchar ( 128 ), 8 分數 int 9 ) 10 11 insert into Score values ( ' 張三 ' , ' 語文 ' , 98 ) 12 insert into Score values ( ' 張三 ' , ' 數學 ' , 89 ) 13 insert into Score values ( ' 張三 ' , ' 物理 ' , 78 ) 14 insert into Score values ( ' 李四 ' , ' 語文 ' , 79 ) 15 insert into Score values ( ' 李四 ' , ' 數學 ' , 88 ) 16 insert into Score values ( ' 李四 ' , ' 物理 ' , 100 ) 17 18 select * from Score
執行結果:
2. 傳統的縱橫表轉換
2.1 縱表轉橫表
先看看我們要轉成的橫表張什么樣子:
既然這個表只有兩列,那么可以根據姓名進行分組。先把姓名拼湊出來,后面的分數我們再想辦法。
sql:
select t.姓名 2 from Score as t 3 group by t.姓名
結果:
?
分析:
- 我們先拿到語文這個科目的分數。既然我們用到了group by 語句,這里肯定要用聚合函數來求分數。
- 而且我們只需要語文這一科的成績,分組出來的 一共有 3列 ,分別是 語文、數學、物理 ?。 ?那么就需要判斷科目來取分數。
? 這里符合我們需求的 case 語句就登場了。他和c#中switch-case 作用一樣。
sql case 語句語法:?
case 字段 when 值1 then 結果 when 值2 then 結果2 ... else 默認結果 end
?
求語文的分數就簡單了:
select t.姓名, SUM ( case t.課程 when ' 語文 ' then t.分數 else 0 end ) as 語文 from Score as t group by t.姓名
結果:
?
既然語文的分數取到了,其他科目改變下條件就可以了。
完整的sql:
select t.姓名, SUM ( case t.課程 when ' 語文 ' then t.分數 else 0 end ) as 語文, SUM ( case t.課程 when ' 數學 ' then t.分數 else 0 end ) as 數學, SUM ( case t.課程 when ' 物理 ' then t.分數 else 0 end ) as 物理 from Score as t group by t.姓名
OK,到這兒,我們傳統方式的縱表轉橫表就大功告成了。
?
2.2?橫表轉縱表
那么我們可以把轉換過來的橫表再轉換回去嗎? ?
我們先把剛剛轉好的表,插入一個新表ScoreHb?中。
1 -- 轉換的表插入新表 2 select t.姓名, 3 SUM ( case t.課程 when ' 語文 ' then t.分數 else 0 end ) as 語文, 4 SUM ( case t.課程 when ' 數學 ' then t.分數 else 0 end ) as 數學, 5 SUM ( case t.課程 when ' 物理 ' then t.分數 else 0 end ) as 物理 6 into ScoreHb 7 from Score as t 8 group by t.姓名
這時ScoreHb 就是我們剛轉換好的橫表,我們再想辦法把他轉回來。
怎么轉呢? 一步步來。我們也先把張三和李四的語文成績查出來。
sql:
1 -- 張三李四語文的分數 2 select t.姓名, 3 ' 語文 ' as 課程, 4 t.語文 as 分數 5 from ScoreHb as t
結果:
還有兩科的數據怎么辦呢? 很簡單,我們一個個都查出來,然后用 union all 把他們組合為一張表就可以了。
sql:
1 -- union all鏈接3個科目 2 select t.姓名, 3 ' 語文 ' as 課程, 4 t.語文 as 分數 5 from ScoreHb as t 6 union all 7 select t.姓名, 8 ' 數學 ' as 課程, 9 t.數學 as 分數 10 from ScoreHb as t 11 union all 12 select t.姓名, 13 ' 物理 ' as 課程, 14 t.物理 as 分數 15 from ScoreHb as t 16 order by t.姓名 desc
?
結果:
?
這樣,我們就把表又變回去了。
但是大家有沒有覺得很麻煩呢?別急,我們有更簡單的辦法。下面為大家介紹pivot關系運算符。
3. 用pivot和unpivot運算符進行轉換
pivot是sql server 2005 提供的運算符,所以只要數據庫在05版本以上的都可以使用。主要用于行和列的轉換。
3.1 pivot縱表轉橫表
sql:
1 select 2 t2.姓名, 3 t2.數學, 4 t2.物理, 5 t2.語文 6 from Score as t1 7 pivot ( sum (分數) for 課程 in (數學,語文,物理)) as t2
結果:
?
是不是代碼簡潔多了。
pivot將原來表中 課程字段中的 數據行 數學,語文,物理 轉換為列,并用sum取對應列的值。
我們只需要記住它的用法就可以了。
?
3.2 unpivot 橫表轉縱表
既然有privot可以縱表轉橫表。那么有沒有運算符幫我們轉回來呢?
答案是肯定的,他就是unpivot
?
sql:
1 select 2 * 3 from 4 ScoreHb 5 unpivot (分數 for 課程 in (語文,數學,物理)) as t4
結果:
?unpivot?將 語文,數學,物理 列轉為行,分數為新的一列存放對應的值。
?是不是比我們之前一個個表查詢拼接,方便了很多。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
