在SSIS
中有一个名为Pivot转换的任务,它将列更改为行,
但如何使用t-sql在sql server中执行相同的任务?
这是我的样本表
location product qty
-----------------------
delhi PEPSI 100
GURGAON CAKE 200
NOIDA APPLE 150
delhi cake 250
所以在使用ssis工具将枢轴转换为ON位置和产品作为枢轴键之后,o / p变为
location pepsi cake apple
delhi 100 null null
GURGAON null 200 null
NOIDA null null 150
delhi null 250 null
答案 0 :(得分:9)
使用PIVOT
表格运算符,如下所示:
SELECT *
FROM tablename
PIVOT
(
MAX(qty)
FOR product IN([pepsi], [cake], [apple])
) as p;
请注意:
我将MAX
聚合函数与qty
一起使用,如果您想要总和使用SUM
或任何其他聚合函数。
您必须手动编写要旋转的列的值,如果要动态执行此操作而不是手动编写,则必须使用动态sql来执行此操作。
像这样:
DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' +
QUOTENAME(product)
FROM tablename
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT @query = 'SELECT *
FROM tablename
PIVOT
(
MAX(qty)
FOR product IN(' + @cols + ')) AS p;';
execute(@query);
答案 1 :(得分:8)
数据透视请求涉及三个逻辑处理阶段,每个阶段都包含相关元素:
因此,在您的案例中根据要求绘制这些阶段:
‘Location’
‘Product’
列值进行,最终列名称为:'Pepsi','Cake','Apple'。‘Qty’
值将被聚合以产生用于分组和传播元素的交叉值将这些值放在标准的Pivot语句中:
SELECT ...
FROM <source_table_or_table_expression>
PIVOT(<agg_func>(<aggregation_element>)
FOR <spreading_element>
IN (<list_of_target_columns>)) AS <result_table_alias>
您的查询变为:
select location ,[PEPSI], [CAKE],[APPLE]
from table1
pivot (sum(qty)
for product
in ( [PEPSI], [CAKE],[APPLE])) AS T
重要的是要注意,使用PIVOT运算符时,您没有显式指定分组元素,因此无需在查询中使用GROUP BY。 PIVOT运营商计算出分组 元素隐式地作为源表(或表表达式)中未指定为扩展元素或聚合元素的所有属性。因此,您必须确保PIVOT运算符的源表除了分组,传播和聚合元素之外没有任何属性,因此在指定传播和聚合元素之后,剩下的唯一属性是您打算作为分组元素的属性。您可以通过不直接将PIVOT运算符应用于原始表来实现此目的,而是将表单表达式仅包含表示旋转元素的属性而不包含其他元素。
select location ,[PEPSI], [CAKE],[APPLE]
from (select location,product,qty
from table1 ) as SourceTable
pivot (sum(qty)
for product
in ( [PEPSI], [CAKE],[APPLE])) AS T
希望这有助于更好地理解Pivot运营商!!
编辑:添加了Unpivot运营商概念:
与Pivoting一样,Unpivoting也涉及3个逻辑阶段:
将这些值放在标准的Unpivot语句中:
SELECT ...
FROM <source_table_or_table_expression>
UNPIVOT(<target_col_to_hold_source_col_values>
FOR <target_col_to_hold_source_col_names> IN(<list_of_source_columns>)) AS
<result_table_alias>;
根据您的案例中的要求映射这些阶段:
<target_col_to_hold_source_col_values>
=包含源列值的列的名称
即:保持列值[Pepsi], [Cake],[Apple]
,即100,250 ......您希望将一个列设为:Qty
<target_col_to_hold_source_col_names>
=包含源列名称的列的名称
即:将列名[Pepsi], [Cake],[Apple]
保存为:product
<list_of_source_columns>
=您感兴趣的源表中列的名称
即:[Pepsi], [Cake],[Apple]
您的查询变为:
SELECT location,product,qty
FROM #temp
UNPIVOT(qty
FOR product
IN([Pepsi],[Cake],[Apple])) AS U;
我在临时表#temp
中添加了上面的Pivot语句的结果。
这里要注意的重点是: 取消隐藏已透视的表格无法恢复原始表格,因为透视会因聚合而导致丢失详细信息。