PIVOT 用于將列值旋轉為列名(即行轉列),在 SQL Server?2000可以用聚合函數配合CASE語句實現
PIVOT 的一般語法是:PIVOT(聚合函數(列) FOR 列 in (…) )AS P
注意:PIVOT、UNPIVOT是SQL Server 2005?的語法,使用需修改數據庫兼容級別( 在數據庫屬性->選項->兼容級別改為 ? 90 )
SQL2008 中可以直接使用
完整語法:
table_source
PIVOT(
聚合函數(value_column)
FOR
pivot_column
IN
(
<
column_list
>
)
)
UNPIVOT 用于將列明轉為列值(即列轉行),在SQL Server 2000可以用UNION來實現
完整語法:
table_source
UNPIVOT(
value_column
FOR
pivot_column
IN
(
<
column_list
>
)
)
?
典型實例
一、行轉列
1 、建立表格
IF
OBJECT_ID
(
'
tb
'
)
IS
NOT
NULL
DROP
TABLE
tb
go
CREATE
TABLE
tb(姓名
VARCHAR
(
10
),課程
VARCHAR
(
10
),分數
INT
)
insert
into
tb
VALUES
(
'
張三
'
,
'
語文
'
,
74
)
insert
into
tb
VALUES
(
'
張三
'
,
'
數學
'
,
83
)
insert
into
tb
VALUES
(
'
張三
'
,
'
物理
'
,
93
)
insert
into
tb
VALUES
(
'
李四
'
,
'
語文
'
,
74
)
insert
into
tb
VALUES
(
'
李四
'
,
'
數學
'
,
84
)
insert
into
tb
VALUES
(
'
李四
'
,
'
物理
'
,
94
)
go
SELECT
*
FROM
tb
go
姓名 ??????? 課程 ??????? 分數
---------- ---------- -----------
張三 ??????? 語文 ??????? 74
張三 ??????? 數學 ??????? 83
張三 ??????? 物理 ??????? 93
李四 ??????? 語文 ??????? 74
李四 ??????? 數學 ??????? 84
李四 ??????? 物理 ??????? 94
?
2 、使用SQL Server 2000靜態SQL
SELECT
姓名,
max
(
CASE
課程
WHEN
'
語文
'
THEN
分數
ELSE
0
END
) 語文,
max
(
CASE
課程
WHEN
'
數學
'
THEN
分數
ELSE
0
END
) 數學,
max
(
CASE
課程
WHEN
'
物理
'
THEN
分數
ELSE
0
END
) 物理
FROM
tb
GROUP
BY
姓名
3 、使用SQL Server 2000動態SQL
--
SQL SERVER 2000動態SQL,指課程不止語文、數學、物理這三門課程。(以下同)
--
變量按sql語言順序賦值
declare
@sqlvarchar
(
500
)
set
@sql
=
'
select姓名
'
select
@sql
=
@sql
+
'
,max(case課程when
'''
+
課程
+
'''
then分數else 0 end)[
'
+
課程
+
'
]
'
from
(selectdistinct課程fromtb)a
--
同from tb group by課程,默認按課程名排序
set
@sql
=
@sql
+
'
from tb group by姓名
'
exec
(
@sql
)
--
使用isnull(),變量先確定動態部分
declare
@sqlvarchar
(
8000
)
select
@sql
=
isnull
(
@sql
+
'
,
'
,
''
)
+
'
max(case課程when
'''
+
課程
+
'''
then分數else 0 end) [
'
+
課程
+
'
]
'
from
(selectdistinct課程fromtb)asa
set
@sql
=
'
select姓名,
'
+
@sql
+
'
from tb group by姓名
'
exec
(
@sql
)
4 、使用SQL Server 2005靜態SQL
SELECT
*
FROM
tb pivot(
MAX
(分數)
FOR
課程
IN
(語文,數學,物理))a
姓名 ??????? 語文 ???????? 數學 ???????? 物理
---------- ----------- ----------- -----------
李四 ??????? 74????????? 84????????? 94
張三 ??????? 74????????? 83????????? 93
5、 使用SQL Server 2005動態SQL
--
使用stuff()
DECLARE
@sql
VARCHAR
(
8000
)
SET
@sql
=
''
--
初始化變量 @sql
SELECT
@sql
=
@sql
+
'
,
'
+
課程
FROM
tb
GROUP
BY
課程
--
變量多值賦值
SET
@sql
=
STUFF
(
@sql
,
1
,
1
,
''
)
--
去掉首個','
SET
@sql
=
'
select * from tb pivot (max(分數) for 課程 in (
'
+
@sql
+
'
))a
'
PRINT
@sql
exec
(
@sql
)
--
或使用isnull()
DECLARE
@sql
VARCHAR
(
8000
)
--
獲得課程集合
SELECT
@sql
=
ISNULL
(
@sql
+
'
,
'
,
''
)
+
課程
FROM
tb
GROUP
BY
課程
SET
@sql
=
'
select * from tb pivot (max(分數) for 課程 in (
'
+
@sql
+
'
))a
'
exec
(
@sql
)
二、行轉列結果加上總分、平均分
1 、使用SQL Server 2000靜態SQL
--
SQL SERVER 2000靜態SQL
select姓名,
max
(case課程when
'
語文
'
then分數else0end)語文,
max
(case課程when
'
數學
'
then分數else0end)數學,
max
(case課程when
'
物理
'
then分數else0end)物理,
sum
(分數)總分,
cast
(
avg
(分數
*
1.0
)asdecimal(
18
,
2
))平均分
fromtb
groupby姓名
姓名 ??????? 語文 ???????? 數學 ???????? 物理 ???????? 總分 ???????? 平均分
---------- ----------- ----------- ----------- -----------
李四 ??????? 74????????? 84????????? 94????????? 252???????? 84.00
張三 ??????? 74????????? 83????????? 93????????? 250???????? 83.33
?
2 、使用SQL Server 2000動態SQL
--
SQL SERVER 2000動態SQL
declare
@sqlvarchar
(
500
)
set
@sql
=
'
select姓名
'
select
@sql
=
@sql
+
'
,max(case課程when
'''
+
課程
+
'''
then分數else 0 end)[
'
+
課程
+
'
]
'
from
(selectdistinct課程fromtb)a
set
@sql
=
@sql
+
'
,sum(分數)總分,cast(avg(分數*1.0) as decimal(18,2)) 平均分from tb group by姓名
'
exec
(
@sql
)
?
3 、使用SQL Server 2005靜態SQL
SELECT
m.
*
,
n.總分 ,
n.平均分
FROM
(
SELECT
*
FROM
tb PIVOT(
MAX
(分數)
FOR
課程
IN
( 語文, 數學, 物理 ) ) a
) m ,
(
SELECT
姓名 ,
SUM
(分數) 總分 ,
CAST
(
AVG
(分數
*
1.0
)
AS
DECIMAL
(
18
,
2
)) 平均分
FROM
tb
GROUP
BY
姓名
) n
WHERE
m.姓名
=
n.姓名
4 、使用SQL Server 2005動態SQL
--
使用stuff()
DECLARE
@sql
VARCHAR
(
8000
)
SET
@sql
=
''
--
初始化變量@sql
SELECT
@sql
=
@sql
+
'
,
'
+
課程
FROM
tb
GROUP
BY
課程
--
變量多值賦值
--
同select @sql = @sql + ','+課程 from (select distinct 課程 from tb)a
SET
@sql
=
STUFF
(
@sql
,
1
,
1
,
''
)
--
去掉首個','
SET
@sql
=
'
select m.* , n.總分,n.平均分 from
(select * from (select * from tb) a pivot (max(分數) for 課程 in (
'
+
@sql
+
'
)) b) m ,
(select 姓名,sum(分數)總分, cast(avg(分數*1.0) as decimal(18,2)) 平均分 from tb group by 姓名) n
where m.姓名= n.姓名
'
EXEC
(
@sql
)
--
或使用isnull()
DECLARE
@sql
VARCHAR
(
8000
)
SELECT
@sql
=
ISNULL
(
@sql
+
'
,
'
,
''
)
+
課程
FROM
tb
GROUP
BY
課程
SET
@sql
=
'
select m.* , n.總分,n.平均分 from
(select * from (select * from tb) a pivot (max(分數) for 課程 in (
'
+
@sql
+
'
)) b) m ,
(select 姓名,sum(分數)總分, cast(avg(分數*1.0) as decimal(18,2)) 平均分 from tb group by 姓名) n
where m.姓名= n.姓名
'
EXEC
(
@sql
)
?
二、列轉行
1 、建立表格
IF
OBJECT_ID
(
'
tb
'
)
IS
NOT
NULL
DROP
TABLE
tb
go
CREATE
TABLE
tb(姓名
VARCHAR
(
10
),語文
INT
,數學
INT
,物理
INT
)
INSERT
INTO
tb
VALUES
(
'
張三
'
,
74
,
83
,
93
)
INSERT
INTO
tb
VALUES
(
'
李四
'
,
74
,
84
,
94
)
go
SELECT
*
FROM
tb
姓名 ??????? 語文 ???????? 數學 ???????? 物理
---------- ----------- ----------- -----------
張三 ???????74????????? 83????????? 93
李四 ??????? 74????????? 84????????? 94
2 、使用SQL Server 2000靜態SQL
--
SQL SERVER 2000靜態SQL。
select
*
from
(
select姓名,課程
=
'
語文
'
,分數
=
語文fromtb
unionall
select姓名,課程
=
'
數學
'
,分數
=
數學fromtb
unionall
select姓名,課程
=
'
物理
'
,分數
=
物理fromtb
) t
orderby姓名,case課程when
'
語文
'
then1when
'
數學
'
then2when
'
物理
'
then3end
姓名 ??????? 課程 ? 分數
---------- ---- -----------
李四 ??????? 語文 ?74
李四 ??????? 數學 ?84
李四 ??????? 物理 ?94
張三 ??????? 語文 ?74
張三 ??????? 數學 ?83
張三 ??????? 物理 ?93
??
2 、使用SQL Server 2000動態SQL
--
SQL SERVER 2000動態SQL。
--
調用系統表動態生態。
declare
@sqlvarchar
(
8000
)
select
@sql
=
isnull
(
@sql
+
'
union all
'
,
''
)
+
'
select姓名, [課程]=
'
+
quotename
(Name,
''''
)
+
'
, [分數] =
'
+
quotename
(Name)
+
'
from tb
'
fromsyscolumns
whereName
!=
'
姓名
'
andID
=
object_id
(
'
tb
'
)
--
表名tb,不包含列名為姓名的其他列
orderbycolid
exec
(
@sql
+
'
order by姓名
'
)
go
?
3 、使用SQL Server 2005靜態SQL
--
SQL SERVER 2005動態SQL
SELECT
姓名 ,
課程 ,
分數
FROM
tb UNPIVOT ( 分數
FOR
課程
IN
(
[
語文
]
,
[
數學
]
,
[
物理
]
) ) t
4 、使用SQL Server 2005動態SQL
--
SQL SERVER 2005動態SQL
DECLARE
@sql
NVARCHAR
(
4000
)
SELECT
@sql
=
ISNULL
(
@sql
+
'
,
'
,
''
)
+
QUOTENAME
(name)
FROM
syscolumns
WHERE
id
=
OBJECT_ID
(
'
tb
'
)
AND
name
NOT
IN
(
'
姓名
'
)
ORDER
BY
colid
SET
@sql
=
'
select 姓名,[課程],[分數] from tb unpivot ([分數] for [課程] in(
'
+
@sql
+
'
))b
'
EXEC
(
@sql
)
?
來自大神張志濤
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

