我是SQL新手。
我有一张这样的表:
ID | TeamID | UserID | ElementID | PhaseID | Effort
-----------------------------------------------------
1 | 1 | 1 | 3 | 5 | 6.74
2 | 1 | 1 | 3 | 6 | 8.25
3 | 1 | 1 | 4 | 1 | 2.23
4 | 1 | 1 | 4 | 5 | 6.8
5 | 1 | 1 | 4 | 6 | 1.5
我被告知要获得这样的数据
ElementID | PhaseID1 | PhaseID5 | PhaseID6
--------------------------------------------
3 | NULL | 6.74 | 8.25
4 | 2.23 | 6.8 | 1.5
我明白我需要使用PIVOT功能。但无法清楚地理解它。 如果有人能够在上述案例中解释它(或任何替代方案,如果有的话),那将是很有帮助的。
答案 0 :(得分:81)
用于将数据从一列旋转到多列的PIVOT
。
对于您的示例,这里是一个STATIC Pivot,意味着您要对要旋转的列进行硬编码:
create table temp
(
id int,
teamid int,
userid int,
elementid int,
phaseid int,
effort decimal(10, 5)
)
insert into temp values (1,1,1,3,5,6.74)
insert into temp values (2,1,1,3,6,8.25)
insert into temp values (3,1,1,4,1,2.23)
insert into temp values (4,1,1,4,5,6.8)
insert into temp values (5,1,1,4,6,1.5)
select elementid
, [1] as phaseid1
, [5] as phaseid5
, [6] as phaseid6
from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in([1], [5], [6])
)p
以下是SQL Demo,其中包含有效版本。
这也可以通过动态PIVOT完成,您可以在其中动态创建列列并执行PIVOT。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.phaseid)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT elementid, ' + @cols + ' from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in (' + @cols + ')
) p '
execute(@query)
两者的结果:
ELEMENTID PHASEID1 PHASEID5 PHASEID6
3 Null 6.74 8.25
4 2.23 6.8 1.5
答案 1 :(得分:6)
这些是非常基本的透视示例,请仔细阅读。
SQL SERVER – PIVOT and UNPIVOT Table Examples
产品表的上述链接示例:
SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT
呈现:
PRODUCT FRED KATE
--------------------
BEER 24 12
MILK 3 1
SODA NULL 6
VEG NULL 5
类似的例子可以在博客文章Pivot tables in SQL Server. A simple sample
中找到答案 2 :(得分:3)
设置兼容性错误
在使用枢轴功能之前使用此功能
ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 100
答案 3 :(得分:3)
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
USE AdventureWorks2008R2 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
DaysToManufacture AverageCost
0 5.0885
1 223.88
2 359.1082
4 949.4105
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost
FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;
Here is the result set.
Cost_Sorted_By_Production_Days 0 1 2 3 4
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
答案 4 :(得分:3)
我是新手,我创建了一篇关于它的好文章...我的问题是理解如何正确应用聚合,这是我的帖子: http://jaider.net/posts/1176-pivot-in-sql-server-correct-aggregated-results/
在@bluefeet解决方案中,重要的是要提到elementid
是您的&#34;隐形&#34;的关键列。 Group By
。
此外,您可以替换elementid
或添加更多列,例如userid
。
答案 5 :(得分:3)
我要添加一些没有人提及的内容。
当源中有3列时,pivot
函数非常有用:一列用于aggregate
,一列扩展为带有for
的列,另一列作为{{1}的枢轴}分发。在产品示例中为row
。
但是,如果源中有更多列,则会将结果分成多行,而不是根据每个附加列的唯一值将每个枢轴分为一行(就像QTY, CUST, PRODUCT
在简单查询中一样)。< / p>
参见此示例,我在源表中添加了一个timestamp列:
现在看到它的影响:
Group By
为解决此问题,您可以像上面每个人一样将子查询作为源进行拉取-只有3列(这并不总是适合您的情况,请设想是否需要放置{{{1 }}的时间戳记条件。
第二种解决方法是使用SELECT CUST, MILK
FROM Product
-- FROM (SELECT CUST, Product, QTY FROM PRODUCT) p
PIVOT (
SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt
ORDER BY CUST
并再次对透视列值进行求和。
where
答案 6 :(得分:0)
数据透视表用于将数据集中的某一列从行转换为列(通常称为扩展列)。在您给出的示例中,这意味着将PhaseID
行转换为一组列,其中PhaseID
可以包含-1、5和6的每个不同值都有一个列。
在您给出的示例中,通过ElementID
列对这些枢轴值进行了分组。
通常,您还需要提供某种形式的 aggregation ,该组合可以为您提供扩展值(PhaseID
)与分组值(ElementID
)。尽管在示例中给出的 aggregation 尚不清楚,但是涉及Effort
列。
完成此枢纽操作后,分组和扩展列用于查找聚合值。或者,对于您来说,ElementID
和PhaseIDX
查找Effort
。
使用分组,扩展,聚合术语,您通常会看到枢轴的示例语法为:
WITH PivotData AS
(
SELECT <grouping column>
, <spreading column>
, <aggregation column>
FROM <source table>
)
SELECT <grouping column>, <distinct spreading values>
FROM PivotData
PIVOT (<aggregation function>(<aggregation column>)
FOR <spreading column> IN <distinct spreading values>));
This提供了图形化的解释,说明了分组,散布和聚合列如何从源转换为透视表(如果有帮助的话)。
答案 7 :(得分:0)
FOR XML PATH 可能不适用于 Microsoft Azure Synapse Serve。一种可能的替代方法,遵循@Tayn 动态生成列的方法,使用 STRING_AGG 获得相同的结果。
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SELECT @cols = STRING_AGG(QUOTENAME(c.phaseid),', ')
/*OPTIONAL: within group (order by cast(t1.[FLOW_SP_SLPM] as INT) asc)*/
FROM (SELECT phaseid FROM temp
GROUP BY phaseid) c
set @query = 'SELECT elementid,' + @cols + ' from
(
select elementid,
phaseid,
effort
from temp
) x
PIVOT
(
max(effort)
for phaseid in (' + @cols + ')
) p '
execute(@query)