SQL Server:使用 PIVOT 行轉列和 UNPIVOT 列轉行


ylbtech-SQL Server:使用 PIVOT 行轉列和 UNPIVOT 列轉行
可以使用 PIVOT 和 UNPIVOT 關系運算符將表值表達式更改為另一個表。PIVOT 通過將表達式某一列中的唯一值轉換為輸出中的多個列來旋轉表值表達式,並在必要時對最終輸出中所需的任何其余列值執行聚合。UNPIVOT 與 PIVOT 執行相反的操作,將表值表達式的列轉換為列值。
【注】對升級到 SQL Server 2005 或更高版本的數據庫使用 PIVOT 和 UNPIVOT 時,必須將數據庫的兼容級別設置為 90 或更高。有關如何設置數據庫兼容級別的信息,請參閱 sp_dbcmptlevel (Transact-SQL)。
 
A,PIVOT 語法 返回頂部
1、

PIVOT 提供的語法比一系列復雜的 SELECT...CASE 語句中所指定的語法更簡單和更具可讀性。有關 PIVOT 語法的完整說明,請參閱 FROM (Transact-SQL)。
以下是帶批注的 PIVOT 語法。

SELECT <非透視的列>,
    [第一個透視的列] AS <列名稱>,
    [第二個透視的列] AS <列名稱>,
    ...
    [最后一個透視的列] AS <列名稱>,
FROM
    (<生成數據的 SELECT 查詢>)
    AS <源查詢的別名>
PIVOT
(
    <聚合函數>(<要聚合的列>)
FOR
[<包含要成為列標題的值的列>]
    IN ( [第一個透視的列], [第二個透視的列],
    ... [最后一個透視的列])
) AS <透視表的別名>
<可選的 ORDER BY 子句>;
2、
B,PIVOT 示例1返回頂部
0、
go
-- ==========================
-- 學生成績表,ByYuanbo
-- ==========================
-- drop table StudentScores;
create table StudentScores
(
username    varchar(20),        --姓名
[subject]    varchar(30),        --科目
score        float,              --成績
);
go
-- 01、插入測試數據
insert into StudentScores(username,[subject],score) values('張三', '語文', 80);
insert into StudentScores(username,[subject],score) values('張三', '語文', 90);
insert into StudentScores(username,[subject],score) values('張三', '數學', 90);
insert into StudentScores(username,[subject],score) values('張三', '英語', 70);
insert into StudentScores(username,[subject],score) values('張三', '生物', 85);
insert into StudentScores(username,[subject],score) values('李四', '語文', 70);
insert into StudentScores(username,[subject],score) values('李四', '數學', 92);
insert into StudentScores(username,[subject],score) values('李四', '數學', 100);
insert into StudentScores(username,[subject],score) values('李四', '英語', 76);
insert into StudentScores(username,[subject],score) values('李四', '生物', 88);
insert into StudentScores(username,[subject],score) values('王二', '語文', 60);
insert into StudentScores(username,[subject],score) values('王二', '數學', 82);
insert into StudentScores(username,[subject],score) values('王二', '英語', 96);
insert into StudentScores(username,[subject],score) values('王二', '生物', 78);
go
-- 02、查詢數據
select * from StudentScores;

--P1、如果我想知道每位學生的每科成績,而且每個學生的全部成績排成一行,這樣方便我查看、統計,導出數據
--A1、傳統 case 方法
select username as '姓名'
,max(case [subject] when '語文' then score else 0 end) as '語文'
,max(case [subject] when '數學' then score else 0 end) as '數學'
,max(case [subject] when '英語' then score else 0 end) as '英語'
,max(case [subject] when '生物' then score else 0 end) as '生物'
from StudentScores
group by username;

/*
以下是帶批注的 PIVOT 語法。
SELECT <非透視的列>,
    [第一個透視的列] AS <列名稱>,
    [第二個透視的列] AS <列名稱>,
    ...
    [最后一個透視的列] AS <列名稱>,
FROM
    (<生成數據的 SELECT 查詢>)
    AS <源查詢的別名>
PIVOT
(
    <聚合函數>(<要聚合的列>)
FOR
[<包含要成為列標題的值的列>]
    IN ( [第一個透視的列], [第二個透視的列],
    ... [最后一個透視的列])
) AS <透視表的別名>
<可選的 ORDER BY 子句>;
*/
go
-- A2:PIVOT 方法
select username as '姓名',[語文],[數學],[英語],[生物] from StudentScores a
PIVOT
(
max(a.score) for a.subject in([語文],[數學],[英語],[生物])
)b;
示例腳本源
1、
P1、如果我想知道每位學生的每科成績,而且每個學生的全部成績排成一行,這樣方便我查看、統計,導出數據
1-1、
--A1、傳統 case 方法
select username as '姓名'
,max(case [subject] when '語文' then score else 0 end) as '語文'
,max(case [subject] when '數學' then score else 0 end) as '數學'
,max(case [subject] when '英語' then score else 0 end) as '英語'
,max(case [subject] when '生物' then score else 0 end) as '生物'
from StudentScores
group by username;
1-2、
-- A2:PIVOT 方法
select username as '姓名',[語文],[數學],[英語],[生物] from StudentScores a
PIVOT
(
max(a.score) for a.subject in([語文],[數學],[英語],[生物])
)b;
1-3、查詢結果
1-4、
2、
C,UNPIVOT 示例1返回頂部
0、
go
-- ==========================
-- 工程詳細表,ByYuanbo
-- ==========================
-- drop table ProjectDetail;
create table ProjectDetail
(
projectName varchar(20),        --功能名稱
overseaSupply int,            --海外供應商供給數量
nativeSupply int,            --國內供應商供給數量
southSupply int,            --南方供應商供給數量
northSupply int                --北方供應商供給數量
);
go
-- 01、添加測試數據
insert into ProjectDetail(projectName,overseaSupply,nativeSupply,southSupply,northSupply)
 values('A', 100, 200, 50, 50);
insert into ProjectDetail(projectName,overseaSupply,nativeSupply,southSupply,northSupply)
 values('B', 200, 300, 150, 150);
insert into ProjectDetail(projectName,overseaSupply,nativeSupply,southSupply,northSupply)
 values('C', 159, 400, 20, 320);
 go
 -- 02、查詢數據
select * from ProjectDetail;

-- P1:查詢項目每個供應商的供給數量?
-- A1:UNPIVOT 方法
select b.projectName,b.supplier,b.supllyNumber from (
select projectName,overseaSupply,nativeSupply,southSupply,northSupply from ProjectDetail) a
UNPIVOT
(
supllyNumber for supplier in(overseaSupply,nativeSupply,southSupply,northSupply)
)b;
示例腳本源
1、
-- P1:查詢項目每個供應商的供給數量?
-- A1:UNPIVOT 方法
select b.projectName,b.supplier,b.supllyNumber from (
select projectName,overseaSupply,nativeSupply,southSupply,northSupply from ProjectDetail) a
UNPIVOT
(
supllyNumber for supplier in(overseaSupply,nativeSupply,southSupply,northSupply)
)b;
2、
D,PIVOT 示例2返回頂部
1、建立一個銷售情況表,其中,year字段表示年份,quarter字段表示季度,amount字段表示銷售額。quarter字段分別用Q1, Q2, Q3, Q4表示一、二、三、四季度。
2、
go
-- ==========================
-- 銷售季度表,ByYuanbo
-- ==========================
-- drop table SalesByQuarter
create table SalesByQuarter
(
year int,            -- 年份
quarter char(2),    -- 季度
amount money        -- 總額
);

go
-- 01、插入數據
set nocount on
declare @index int
declare @q int
set @index = 0
declare @year int
while (@index < 30)
begin
    set @year = 2005 + (@index % 4)
    set @q = (CasT((RAND() * 500) as int) % 4) + 1
    insert into SalesByQuarter values(@year, 'Q' + CasT(@q as char(1)), RAND() * 10000.00)
    set @index = @index + 1
end;
go
-- 02、查詢
select * from SalesByQuarter;
go
-- 03、傳統 CASE 方法
select year as 年份
,sum(case when quarter = 'Q1' then amount else 0 end) 一季度
,sum(case when quarter = 'Q2' then amount else 0 end) 二季度
,sum(case when quarter = 'Q3' then amount else 0 end) 三季度
,sum(case when quarter = 'Q4' then amount else 0 end) 四季度
from SalesByQuarter
group by year
order by year desc;
go
-- 04、PIVOT 方法
select year as 年份, Q1 as 一季度, Q2 as 二季度, Q3 as 三季度, Q4 as 四季度 from SalesByQuarter
PIVOT(SUM (amount) FOR quarter IN (Q1, Q2, Q3, Q4) )P
order by year desc;
示例腳本源
3、
E,返回頂部
 
F,返回頂部
 
G,相關資源返回頂部
1、官方示例
1,
H,返回頂部
 
warn 作者:ylbtech
出處:http://storebook.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM