午夜国产狂喷潮在线观看|国产AⅤ精品一区二区久久|中文字幕AV中文字幕|国产看片高清在线

    重溫SQL——行轉(zhuǎn)列,列轉(zhuǎn)行
    來源:易賢網(wǎng) 閱讀:1353 次 日期:2015-05-04 14:25:38
    溫馨提示:易賢網(wǎng)小編為您整理了“重溫SQL——行轉(zhuǎn)列,列轉(zhuǎn)行”,方便廣大網(wǎng)友查閱!

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

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

    CREATE TABLE [StudentScores]

    (

    [UserName] NVARCHAR(20), --學(xué)生姓名

    [Subject] NVARCHAR(30), --科目

    [Score] FLOAT, --成績

    )

    INSERT INTO [StudentScores] SELECT 'Nick', '語文', 80

    INSERT INTO [StudentScores] SELECT 'Nick', '數(shù)學(xué)', 90

    INSERT INTO [StudentScores] SELECT 'Nick', '英語', 70

    INSERT INTO [StudentScores] SELECT 'Nick', '生物', 85

    INSERT INTO [StudentScores] SELECT 'Kent', '語文', 80

    INSERT INTO [StudentScores] SELECT 'Kent', '數(shù)學(xué)', 90

    INSERT INTO [StudentScores] SELECT 'Kent', '英語', 70

    INSERT INTO [StudentScores] SELECT 'Kent', '生物', 85

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

    SELECT

    UserName,

    MAX(CASE Subject WHEN '語文' THEN Score ELSE 0 END) AS '語文',

    MAX(CASE Subject WHEN '數(shù)學(xué)' THEN Score ELSE 0 END) AS '數(shù)學(xué)',

    MAX(CASE Subject WHEN '英語' THEN Score ELSE 0 END) AS '英語',

    MAX(CASE Subject WHEN '生物' THEN Score ELSE 0 END) AS '生物'

    FROM dbo.[StudentScores]

    GROUP BY UserName

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

    名單

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

    CREATE TABLE [Inpours]

    (

    [ID] INT IDENTITY(1,1),

    [UserName] NVARCHAR(20), --游戲玩家

    [CreateTime] DATETIME, --充值時(shí)間

    [PayType] NVARCHAR(20), --充值類型

    [Money] DECIMAL, --充值金額

    [IsSuccess] BIT, --是否成功 1表示成功, 0表示失敗

    CONSTRAINT [PK_Inpours_ID] PRIMARY KEY(ID)

    )

    INSERT INTO Inpours SELECT '張三', '2010-05-01', '支付寶', 50, 1

    INSERT INTO Inpours SELECT '張三', '2010-06-14', '支付寶', 50, 1

    INSERT INTO Inpours SELECT '張三', '2010-06-14', '手機(jī)短信', 100, 1

    INSERT INTO Inpours SELECT '李四', '2010-06-14', '手機(jī)短信', 100, 1

    INSERT INTO Inpours SELECT '李四', '2010-07-14', '支付寶', 100, 1

    INSERT INTO Inpours SELECT '王五', '2010-07-14', '工商銀行卡', 100, 1

    INSERT INTO Inpours SELECT '趙六', '2010-07-14', '建設(shè)銀行卡', 100, 1

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

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,

    CASE PayType WHEN '支付寶' THEN SUM(Money) ELSE 0 END AS '支付寶',

    CASE PayType WHEN '手機(jī)短信' THEN SUM(Money) ELSE 0 END AS '手機(jī)短信',

    CASE PayType WHEN '工商銀行卡' THEN SUM(Money) ELSE 0 END AS '工商銀行卡',

    CASE PayType WHEN '建設(shè)銀行卡' THEN SUM(Money) ELSE 0 END AS '建設(shè)銀行卡'

    FROM Inpours

    GROUP BY CreateTime, PayType

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

    名單1

    SELECT

    CreateTime,

    ISNULL(SUM([支付寶]) , 0) AS [支付寶] ,

    ISNULL(SUM([手機(jī)短信]) , 0) AS [手機(jī)短信] ,

    ISNULL(SUM([工商銀行卡]), 0) AS [工商銀行卡] ,

    ISNULL(SUM([建設(shè)銀行卡]), 0) AS [建設(shè)銀行卡]

    FROM

    (

    SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,

    CASE PayType WHEN '支付寶' THEN SUM(Money) ELSE 0 END AS '支付寶' ,

    CASE PayType WHEN '手機(jī)短信' THEN SUM(Money) ELSE 0 END AS '手機(jī)短信',

    CASE PayType WHEN '工商銀行卡' THEN SUM(Money) ELSE 0 END AS '工商銀行卡',

    CASE PayType WHEN '建設(shè)銀行卡' THEN SUM(Money) ELSE 0 END AS '建設(shè)銀行卡'

    FROM Inpours

    GROUP BY CreateTime, PayType

    ) T

    GROUP BY CreateTime

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

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->DECLARE @cmdText VARCHAR(8000);

    DECLARE @tmpSql VARCHAR(8000);

    SET @cmdText = 'SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,' + CHAR(10);

    SELECT @cmdText = @cmdText + ' CASE PayType WHEN ''' + PayType + ''' THEN SUM(Money) ELSE 0 END AS ''' + PayType

    + ''',' + CHAR(10) FROM (SELECT DISTINCT PayType FROM Inpours ) T

    SET @cmdText = LEFT(@cmdText, LEN(@cmdText) -2) --注意這里,如果沒有加CHAR(10) 則用LEFT(@cmdText, LEN(@cmdText) -1)

    SET @cmdText = @cmdText + ' FROM Inpours GROUP BY CreateTime, PayType ';

    SET @tmpSql ='SELECT CreateTime,' + CHAR(10);

    SELECT @tmpSql = @tmpSql + ' ISNULL(SUM(' + PayType + '), 0) AS ''' + PayType + ''',' + CHAR(10)

    FROM (SELECT DISTINCT PayType FROM Inpours ) T

    SET @tmpSql = LEFT(@tmpSql, LEN(@tmpSql) -2) + ' FROM (' + CHAR(10);

    SET @cmdText = @tmpSql + @cmdText + ') T GROUP BY CreateTime ';

    PRINT @cmdText

    EXECUTE (@cmdText);

    下面是通過PIVOT來進(jìn)行行轉(zhuǎn)列的用法,大家可以對比一下,確實(shí)要簡單、更具可讀性(呵呵,習(xí)慣的前提下)

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->SELECT

    CreateTime, [支付寶] , [手機(jī)短信],

    [工商銀行卡] , [建設(shè)銀行卡]

    FROM

    (

    SELECT CONVERT(VARCHAR(10), CreateTime, 120) AS CreateTime,PayType, Money

    FROM Inpours

    ) P

    PIVOT (

    SUM(Money)

    FOR PayType IN

    ([支付寶], [手機(jī)短信], [工商銀行卡], [建設(shè)銀行卡])

    ) AS T

    ORDER BY CreateTime

    有時(shí)可能會(huì)出現(xiàn)這樣的錯(cuò)誤:

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

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

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

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

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->CREATE TABLE ProgrectDetail

    (

    ProgrectName NVARCHAR(20), --工程名稱

    OverseaSupply INT, --海外供應(yīng)商供給數(shù)量

    NativeSupply INT, --國內(nèi)供應(yīng)商供給數(shù)量

    SouthSupply INT, --南方供應(yīng)商供給數(shù)量

    NorthSupply INT --北方供應(yīng)商供給數(shù)量

    )

    INSERT INTO ProgrectDetail

    SELECT 'A', 100, 200, 50, 50

    UNION ALL

    SELECT 'B', 200, 300, 150, 150

    UNION ALL

    SELECT 'C', 159, 400, 20, 320

    UNION ALL

    SELECT 'D', 250, 30, 15, 15

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

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->SELECT ProgrectName, 'OverseaSupply' AS Supplier,

    MAX(OverseaSupply) AS 'SupplyNum'

    FROM ProgrectDetail

    GROUP BY ProgrectName

    UNION ALL

    SELECT ProgrectName, 'NativeSupply' AS Supplier,

    MAX(NativeSupply) AS 'SupplyNum'

    FROM ProgrectDetail

    GROUP BY ProgrectName

    UNION ALL

    SELECT ProgrectName, 'SouthSupply' AS Supplier,

    MAX(SouthSupply) AS 'SupplyNum'

    FROM ProgrectDetail

    GROUP BY ProgrectName

    UNION ALL

    SELECT ProgrectName, 'NorthSupply' AS Supplier,

    MAX(NorthSupply) AS 'SupplyNum'

    FROM ProgrectDetail

    GROUP BY ProgrectName

    名單2

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

    代碼

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->SELECT ProgrectName,Supplier,SupplyNum

    FROM

    (

    SELECT ProgrectName, OverseaSupply, NativeSupply,

    SouthSupply, NorthSupply

    FROM ProgrectDetail

    )T

    UNPIVOT

    (

    SupplyNum FOR Supplier IN

    (OverseaSupply, NativeSupply, SouthSupply, NorthSupply )

    ) P

    更多信息請查看IT技術(shù)專欄

    更多信息請查看數(shù)據(jù)庫
    易賢網(wǎng)手機(jī)網(wǎng)站地址:重溫SQL——行轉(zhuǎn)列,列轉(zhuǎn)行
    由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

    2025國考·省考課程試聽報(bào)名

    • 報(bào)班類型
    • 姓名
    • 手機(jī)號(hào)
    • 驗(yàn)證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
    工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
    云南網(wǎng)警備案專用圖標(biāo)
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
    云南網(wǎng)警報(bào)警專用圖標(biāo)