成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SQL 中的行轉(zhuǎn)列和列轉(zhuǎn)行

數(shù)據(jù)庫 SQL Server
行轉(zhuǎn)列,列轉(zhuǎn)行是我們在開發(fā)過程中經(jīng)常碰到的問題。行轉(zhuǎn)列一般通過CASE WHEN 語句來實現(xiàn),也可以通過 SQL SERVER 的運算符PIVOT來實現(xiàn)。

 行轉(zhuǎn)列,列轉(zhuǎn)行是我們在開發(fā)過程中經(jīng)常碰到的問題。行轉(zhuǎn)列一般通過CASE WHEN 語句來實現(xiàn),也可以通過 SQL SERVER 的運算符PIVOT來實現(xiàn)。用傳統(tǒng)的方法,比較好理解。層次清晰,而且比較習慣。 但是PIVOT 、UNPIVOT提供的語法比一系列復雜的SELECT…CASE 語句中所指定的語法更簡單、更具可讀性。下面我們通過幾個簡單的例子來介紹一下列轉(zhuǎn)行、行轉(zhuǎn)列問題。

[[433974]]

我們首先先通過一個老生常談的例子,學生成績表(下面簡化了些)來形象了解下行轉(zhuǎn)列

 

  1. CREATE  TABLE [StudentScores] 
  2.   [UserName]         NVARCHAR(20),        --學生姓名 
  3.    [Subject]          NVARCHAR(30),        --科目 
  4.    [Score]            FLOAT,               --成績 
  5.  
  6. INSERT INTO [StudentScores] SELECT 'Nick''語文', 80 
  7. INSERT INTO [StudentScores] SELECT 'Nick''數(shù)學', 90 
  8. INSERT INTO [StudentScores] SELECT 'Nick''英語', 70 
  9. INSERT INTO [StudentScores] SELECT 'Nick''生物', 85 
  10. INSERT INTO [StudentScores] SELECT 'Kent''語文', 80 
  11. INSERT INTO [StudentScores] SELECT 'Kent''數(shù)學', 90 
  12. INSERT INTO [StudentScores] SELECT 'Kent''英語', 70 
  13. INSERT INTO [StudentScores] SELECT 'Kent''生物', 85 

如果我想知道每位學生的每科成績,而且每個學生的全部成績排成一行,這樣方便我查看、統(tǒng)計,導出數(shù)據(jù)

 

  1. SELECT 
  2.      UserName, 
  3.      MAX(CASE Subject WHEN '語文' THEN Score ELSE 0 ENDAS '語文'
  4.      MAX(CASE Subject WHEN '數(shù)學' THEN Score ELSE 0 ENDAS '數(shù)學'
  5.      MAX(CASE Subject WHEN '英語' THEN Score ELSE 0 ENDAS '英語'
  6.      MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 ENDAS '生物' 
  7. FROM dbo.[StudentScores] 
  8. GROUP BY UserName 

 

查詢結果如圖所示,這樣我們就能很清楚的了解每位學生所有的成績了

 

 

接下來我們來看看第二個小列子。有一個游戲玩家充值表(僅僅為了說明,舉的一個小例子),

 

 

 

  1. CREATE TABLE [Inpours] 
  2.   [ID]                INT IDENTITY(1,1), 
  3.   [UserName]          NVARCHAR(20),  --游戲玩家 
  4.    [CreateTime]        DATETIME,      --充值時間 
  5.    [PayType]           NVARCHAR(20),  --充值類型 
  6.    [Money]             DECIMAL,       --充值金額 
  7.    [IsSuccess]         BIT,           --是否成功 1表示成功, 0表示失敗 
  8.    CONSTRAINT [PK_Inpours_ID] PRIMARY KEY(ID) 
  9. INSERT INTO Inpours SELECT '張三''2010-05-01''支付寶', 50, 1 
  10. INSERT INTO Inpours SELECT '張三''2010-06-14''支付寶', 50, 1 
  11. INSERT INTO Inpours SELECT '張三''2010-06-14''手機短信', 100, 1 
  12. INSERT INTO Inpours SELECT '李四''2010-06-14''手機短信', 100, 1 
  13. INSERT INTO Inpours SELECT '李四''2010-07-14''支付寶', 100, 1 
  14. INSERT INTO Inpours SELECT '王五''2010-07-14''工商銀行卡', 100, 1 
  15. INSERT INTO Inpours SELECT '趙六''2010-07-14''建設銀行卡', 100, 1 

下面來了一個統(tǒng)計數(shù)據(jù)的需求,要求按日期、支付方式來統(tǒng)計充值金額信息。這也是一個典型的行轉(zhuǎn)列的例子。我們可以通過下面的腳本來達到目的

 

  1. SELECT 
  2.       CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime, 
  3.       CASE PayType WHEN '支付寶'     THEN SUM(Money) ELSE 0 END AS '支付寶'
  4.       CASE PayType WHEN '手機短信'    THEN SUM(Money) ELSE 0 END AS '手機短信'
  5.       CASE PayType WHEN '工商銀行卡'  THEN SUM(Money) ELSE 0 END AS '工商銀行卡'
  6.       CASE PayType WHEN '建設銀行卡'  THEN SUM(Money) ELSE 0 END AS '建設銀行卡' 
  7. FROM Inpours 
  8. GROUP BY CreateTime, PayType 

如圖所示,我們這樣只是得到了這樣的輸出結果,還需進一步處理,才能得到想要的結果

 

 

 

 

 

  1. SELECT 
  2.       CreateTime, 
  3.       ISNULL(SUM([支付寶])    , 0)  AS [支付寶], 
  4.       ISNULL(SUM([手機短信])  , 0)  AS [手機短信], 
  5.       ISNULL(SUM([工商銀行卡]), 0)  AS [工商銀行卡],   
  6.       ISNULL(SUM([建設銀行卡]), 0)  AS [建設銀行卡] 
  7. FROM 
  8.    SELECT 
  9.           CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime, 
  10.           CASE PayType WHEN '支付寶'     THEN SUM(Money) ELSE 0 END AS '支付寶' , 
  11.           CASE PayType WHEN '手機短信'   THEN SUM(Money) ELSE 0 END AS '手機短信'
  12.           CASE PayType WHEN '工商銀行卡' THEN SUM(Money) ELSE 0 END AS '工商銀行卡'
  13.           CASE PayType WHEN '建設銀行卡' THEN SUM(Money) ELSE 0 END AS '建設銀行卡' 
  14.    FROM Inpours 
  15.    GROUP BY CreateTime, PayType 
  16. ) T 
  17. GROUP BY CreateTime 

其實行轉(zhuǎn)列,關鍵是要理清邏輯,而且對分組(Group by)概念比較清晰。上面兩個列子基本上就是行轉(zhuǎn)列的類型了。但是有個問題來了,上面是我為了說明弄的一個簡單列子。實際中,可能支付方式特別多,而且邏輯也復雜很多,可能涉及匯率、手續(xù)費等等(曾經(jīng)做個這樣一個),如果支付方式特別多,我們的CASE WHEN 會弄出一大堆,確實比較惱火,而且新增一種支付方式,我們還得修改腳本如果把上面的腳本用動態(tài)SQL改寫一下,我們就能輕松解決這個問題

 

  1. DECLARE @cmdText    VARCHAR(8000); 
  2. DECLARE @tmpSql        VARCHAR(8000); 
  3. SET @cmdText = 'SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,' + CHAR(10); 
  4. SELECT @cmdText = @cmdText + ' CASE PayType WHEN ''' + 
  5. PayType + ''' THEN SUM(Money) ELSE 0 END AS ''' + PayType 
  6.       + ''',' + CHAR(10)  FROM (SELECT DISTINCT PayType FROM Inpours ) T 
  7.  
  8. SET @cmdText = LEFT(@cmdText, LEN(@cmdText) -2) --注意這里,如果沒有加CHAR(10) 則用LEFT(@cmdText, LEN(@cmdText) -1) 
  9.  
  10. SET @cmdText = @cmdText + ' FROM Inpours     
  11.    GROUP BY CreateTime, PayType '; 
  12.  
  13. SET @tmpSql ='SELECT CreateTime,' + CHAR(10); 
  14. SELECT @tmpSql = @tmpSql + ' ISNULL(SUM(' + PayType  + '), 0) AS ''' + 
  15. PayType  + ''','  + CHAR(10) 
  16. FROM  (SELECT DISTINCT PayType FROM Inpours ) T 
  17.  
  18. SET @tmpSql = LEFT(@tmpSql, LEN(@tmpSql) -2) + ' FROM (' + CHAR(10); 
  19.  
  20. SET @cmdText = @tmpSql + @cmdText + ') T GROUP BY CreateTime '
  21. PRINT @cmdText 
  22. EXECUTE (@cmdText); 

下面是通過PIVOT來進行行轉(zhuǎn)列的用法,大家可以對比一下,確實要簡單、更具可讀性

 

  1. SELECT CreateTime, [支付寶] , [手機短信],[工商銀行卡] , [建設銀行卡] 
  2. FROM 
  3.    SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,PayType, Money 
  4.    FROM Inpours 
  5. ) P 
  6. PIVOT ( 
  7.            SUM(Money) 
  8.            FOR PayType IN 
  9.            ([支付寶], [手機短信], [工商銀行卡], [建設銀行卡]) 
  10.      ) AS T 
  11. ORDER BY CreateTime 

有時可能會出現(xiàn)這樣的錯誤:

消息 325,級別 15,狀態(tài) 1,第 9 行

‘PIVOT’ 附近有語法錯誤。您可能需要將當前數(shù)據(jù)庫的兼容級別設置為更高的值,以啟用此功能。有關存儲過程 sp_dbcmptlevel 的信息,請參見幫助。

這個是因為:對升級到 SQL Server 2005 或更高版本的數(shù)據(jù)庫使用 PIVOT 和 UNPIVOT 時,必須將數(shù)據(jù)庫的兼容級別設置為 90 或更高。有關如何設置數(shù)據(jù)庫兼容級別的信息,請參閱 sp_dbcmptlevel (Transact-SQL)。 例如,只需在執(zhí)行上面腳本前加上 EXEC sp_dbcmptlevel Test, 90; 就OK了, Test 是所在數(shù)據(jù)庫的名稱。

下面我們來看看列轉(zhuǎn)行,主要是通過UNION ALL ,MAX來實現(xiàn)。假如有下面這么一個表

 

  1. Create Table ProgrectDetail 
  2.    ProgrectName         NVARCHAR(20), --工程名稱 
  3.    OverseaSupply        INT,          --海外供應商供給數(shù)量 
  4.    NativeSupply         INT,          --國內(nèi)供應商供給數(shù)量 
  5.    SouthSupply          INT,          --南方供應商供給數(shù)量 
  6.    NorthSupply          INT           --北方供應商供給數(shù)量 
  7.  
  8. INSERT INTO ProgrectDetail 
  9. SELECT 'A', 100, 200, 50, 50 
  10. UNION ALL 
  11. SELECT 'B', 200, 300, 150, 150 
  12. UNION ALL 
  13. SELECT 'C', 159, 400, 20, 320 
  14. UNION ALL 
  15. SELECT 'D', 250, 30, 15, 15 

我們可以通過下面的腳本來實現(xiàn),查詢結果如下圖所示

 

  1. SELECT  ProgrectName, 'OverseaSupply' AS Supplier, 
  2.       MAX(OverseaSupply) AS 'SupplyNum' 
  3. FROM ProgrectDetail 
  4. GROUP BY ProgrectName 
  5. UNION ALL 
  6. SELECT ProgrectName, 'NativeSupply' AS Supplier, 
  7.        MAX(NativeSupply) AS 'SupplyNum' 
  8. FROM ProgrectDetail 
  9. GROUP BY ProgrectName 
  10. UNION ALL 
  11. SELECT ProgrectName, 'SouthSupply' AS Supplier, 
  12.        MAX(SouthSupply) AS 'SupplyNum' 
  13. FROM ProgrectDetail 
  14. GROUP BY ProgrectName 
  15. UNION ALL 
  16. SELECT ProgrectName, 'NorthSupply' AS Supplier, 
  17.        MAX(NorthSupply) AS 'SupplyNum' 
  18. FROM ProgrectDetail 
  19. GROUP BY ProgrectName 

 

 

 

用UNPIVOT 實現(xiàn)如下:

 

  1. SELECT ProgrectName,Supplier,SupplyNum 
  2. FROM   
  3.    SELECT ProgrectName, OverseaSupply, NativeSupply, 
  4.           SouthSupply, NorthSupply 
  5.     FROM ProgrectDetail 
  6. )T 
  7. UNPIVOT   
  8.    SupplyNum FOR Supplier IN 
  9.    (OverseaSupply, NativeSupply, SouthSupply, NorthSupply ) 
  10. ) P 

 

責任編輯:華軒 來源: SQL數(shù)據(jù)庫開發(fā)
相關推薦

2021-06-23 10:13:00

SQL行轉(zhuǎn)列列轉(zhuǎn)行

2010-07-28 09:09:55

SQL

2024-10-16 21:17:59

2021-12-16 22:59:21

SQL報表應用

2020-02-17 11:08:44

JavaExcel辦公

2010-07-13 16:20:30

SQL Server數(shù)

2010-07-16 08:50:00

SQL Server表

2025-04-03 08:00:51

2010-07-13 16:07:26

SQL Server行

2010-11-03 14:52:26

DB2列轉(zhuǎn)行

2011-07-15 09:04:42

PIVOTUNPIVOT

2010-09-06 14:05:36

SQL相加字符串

2014-07-10 10:09:11

JSON數(shù)據(jù)行轉(zhuǎn)列

2021-10-14 06:51:55

數(shù)據(jù)庫SQL

2010-09-01 16:47:18

SQL刪除

2009-06-22 10:22:57

SQL Server

2010-11-03 14:28:15

DB2行轉(zhuǎn)列

2010-09-01 15:30:24

SQL刪除

2011-03-17 16:46:50

SQL Server存儲方式

2010-09-06 11:57:33

sql server語句
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91热爆在线观看 | 在线免费观看日本视频 | 理伦毛片 | 国产高清视频在线观看 | 亚洲国产一区二区视频 | 久久成人精品 | 天天射天天操天天干 | 91免费福利在线 | 久久精品亚洲精品国产欧美kt∨ | av第一页 | 国产精品96久久久久久 | 欧美网址在线观看 | 在线 丝袜 欧美 日韩 制服 | 仙人掌旅馆在线观看 | 99福利在线观看 | 精品区一区二区 | 北条麻妃99精品青青久久主播 | 国产福利视频在线观看 | 一区欧美 | 欧美日韩中文字幕 | 日韩中文字幕久久 | 精品国产视频 | 免费国产一区二区视频 | 中文字幕一区二区三区四区不卡 | 亚洲综合日韩精品欧美综合区 | 日本特黄a级高清免费大片 成年人黄色小视频 | 亚洲精品在线观看网站 | 日韩成人av在线 | 自拍偷拍第一页 | 狠狠干网站 | 日韩精品成人一区二区三区视频 | 在线观看国产www | 亚洲午夜视频在线观看 | 日本不卡免费新一二三区 | 毛片在线看片 | 国产综合精品 | 亚洲av毛片成人精品 | 亚洲精品一 | 91中文字幕在线观看 | 91视频一区二区 | 人人99|