SELECT * FROM
(SELECT TOP (1000) *
FROM [HerPeisTJTLTJZX].[dbo].[viDd]
WHERE nian ='2023' and yue='4'
)A
SELECT org,[1],[2],[3],[4],[5],[6],[7]
FROM [HerPeisTJTLTJZX].[dbo].[viDd]
PIVOT
(
SUM(rsvCnt) for [yao] in ([1],[2],[3],[4],[5],[6],[7])
) TBL
where zhou=datepart(wk,'2023-04-17') and org is not null
and ([20230405] is not null)
SELECT org,[20230403],[20230404],[20230405]
FROM [HerPeisTJTLTJZX].[dbo].[viDd]
PIVOT
(
SUM(rsvCnt) for [ddStr] in ([20230403],[20230404],[20230405])--select dd from [HerPeisTJTLTJZX].[dbo].[viDd] WHERE yy ='2023' and mm ='4' )
) TBL
where org is not null
and ([20230405] is not null)
set datefirst 1
select datepart(weekday, getdate())
select datepart(dd, getdate())
PIVOT函数
将商品类型列中的值转换为列标题
SELECT 商店名,[短袖],[裤子]
FROM 销售
PIVOT(SUM(销售量) FOR 商品类型 IN ([短袖],[裤子])) a
商店名 短袖 裤子
安踏 20 56
李宁 30 60
安踏 61 60
李宁 40 80
安踏 55 78
李宁 50 90
明明SELECT语句中有商店名,怎么没有对商店名进行分组,为什么安踏和李宁出现三次,安踏短袖的销售数量不显示总和136,是不是有点像仅仅进行了行列转换?
这实际上与SQL语句的执行顺序有关,销售表中包含四列,分别为商店名,商品类型,销售量和日期,上述语句执行步骤类似如下:
1. 首先,对非聚合列进行分组,然后对聚合列进行统计
商店名,商品类型,销售日期为非聚合列,销售量为聚合列,商品类型既是非聚合列也是要成为列标题的列
SELECT 商店名,商品类型,销售日期,SUM(销售量) FROM 销售 GROUP BY 商店名,商品类型, 销售日期
2.其次,将要成为列标题的值转化为透视列,值为聚合函数对应的值
具体为将商品类型列中的值转换为列标题,值为SUM(销售量)对应的值
3. 最后,从这个表中筛选出列
上述语句相当于筛选出商店名,短袖和裤子这三列
SELECT 商店名,日期,[短袖],[裤子]
FROM 销售
PIVOT(SUM(销售量) FOR 商品类型 IN ([短袖],[裤子])) a
商店名 日期 短袖 裤子
安踏 2021-04-27 20 56
李宁 2021-04-27 30 60
安踏 2021-04-28 61 60
李宁 2021-04-28 40 80
安踏 2021-04-29 55 78
李宁 2021-04-29 50 90
SELECT 商店名,[短袖],[裤子] FROM 销售 PIVOT(SUM(销售量) FOR 商品类型 IN ([短袖],[裤子])) a 和 SELECT 商店名,日期,[短袖],[裤子] FROM 销售 PIVOT(SUM(销售量) FOR 商品类型 IN ([短袖],[裤子])) a本质上是一样的,只是最后筛选出的列不同,换句话说PIVOT函数会对源表中除聚合列以外的所有列进行分组GROUP BY,即使SELECT语句中没有出现一些非聚合列
为了实现这段时间内各个商店各商品类型销售总额,需要在源表上进行调整
统计这段时间内各个商店各商品类型销售总额,并将商品类型列中的值转换为列标题
SELECT 商店名,[短袖],[裤子]
FROM (SELECT 商店名,商品类型,销售量 FROM 销售) b
PIVOT(SUM(销售量) FOR 商品类型 IN ([短袖],[裤子])) a
商店名 短袖 裤子
安踏 136 194
李宁 120 230
综上,无论是利用CASE还是PIVOT进行透视功能,需要搞清楚是仅仅要实现行列转换,还是需要分组统计后再进行行列转换,不同的需求SQL语句会有差异,另外,对同一需求CASE和PIVOT的思路也是存在差异的
SQL SERVER PIVOT操作
PIVOT和UNPIVOT
PIVOT 通过将表达式中的一个列的唯一值转换为输出中的多列(即行转列),来轮替表值表达式。PIVOT 在需要对最终输出所需的所有剩余列值执行聚合时运行聚合。与 PIVOT 执行的操作相反,UNPIVOT 将表值表达式的列轮换为行(即列转行)。
但是需要注意得是,UNPIVOT 并不完全是 PIVOT 的逆操作。PIVOT 执行聚合,并将多个可能的行合并为输出中的一行。UNPIVOT 不重现原始表值表达式的结果,因为行已被合并。
-- PIVOT 语法
SELECT <非透视的列>,
[第一个透视的列] AS <列名称>,
[第二个透视的列] AS <列名称>,
...
[最后一个透视的列] AS <列名称>,
FROM
(<生成数据的 SELECT 查询>)
AS <源查询的别名>
PIVOT
(
<聚合函数>(<要聚合的列>)
FOR
[<包含要成为列标题的值的列>]
IN ( [第一个透视的列], [第二个透视的列],
... [最后一个透视的列])
) AS <透视表的别名>
<可选的 ORDER BY 子句>;