没有聚合功能的TSQL Pivot


139

我有这样的桌子...

CustomerID   DBColumnName   Data
--------------------------------------
1            FirstName      Joe
1            MiddleName     S
1            LastName       Smith
1            Date           12/12/2009
2            FirstName      Sam
2            MiddleName     S
2            LastName       Freddrick
2            Date           1/12/2009
3            FirstName      Jaime
3            MiddleName     S
3            LastName       Carol
3            Date           12/1/2009

我想要这个

使用PIVOT可以吗?

CustomerID  FirstName   MiddleName          LastName        Date
----------------------------------------------------------------------
1           Joe             S               Smith           12/12/2009
2           Sam             S               Freddrick       1/12/2009
3           Jaime           S               Carol           12/1/2009

Answers:


102

您可以使用MAX聚合,它将仍然有效。一个值的最大值=该值。

在这种情况下,您还可以在customerid上自我连接5次,并按每个表引用按dbColumnName进行过滤。它可能会更好。


1
如果您有2位姓氏相同的化妆师,这实际上是行不通的
Leonardo

1
那可行。请记住,DBColumnName是元数据-您实际上是按“ CustomerID = 1 AND DBColumnName ='FirstName'”进行过滤。当然,如果给定的CustomerID有多个FirstName行,则此方法会中断,但是如果您正确创建表,则CustomerID和DBColumnName都是主键的一部分...
4AM

7
一些代码/模拟作为示例将是不错的选择,并且可以完美地完成此答案。
DavidScherer

167

是的,但是为什么 !!??

   Select CustomerID,
     Min(Case DBColumnName When 'FirstName' Then Data End) FirstName,
     Min(Case DBColumnName When 'MiddleName' Then Data End) MiddleName,
     Min(Case DBColumnName When 'LastName' Then Data End) LastName,
     Min(Case DBColumnName When 'Date' Then Data End) Date
   From table
   Group By CustomerId

2
^^这对我有用。PIVOT对于非数字值无效。
Dienekes 2010年

6
这是一个很好的选择。我Pivot在查询中使用过,然后切换到该位置,并查看了将两者一起运行的执行计划。这种方法花费了8%,而Pivot方法花费了92%!
mafue 2012年

2
@CharlesBretana,您太棒了!你救了我的灵魂!)那是最好的解决方案。谢谢!
Chaki_Black

3
真的很喜欢这种解决方案,它还可以确保列包含正确的数据而不是Pivot数据,谢谢!
Tenerezza

2
这项工作很棒!但是,我该如何预防-– Warning: Null value is eliminated by an aggregate or other SET operation
GiddyUpHorsey

22
WITH pivot_data AS
(
SELECT customerid, -- Grouping Column
dbcolumnname, -- Spreading Column
data -- Aggregate Column
FROM pivot2 
)
SELECT customerid, [firstname], [middlename], [lastname]
FROM pivot_data
PIVOT (max(data) FOR dbcolumnname IN ([firstname],[middlename],[lastname])) AS p;

3
这应该是可接受的答案,因为它显示了TSQL Pivot命令的正确使用。
Ubercoder '19

1
值得注意的是,在此查询中,“ pivot2”是原始数据所在的表的名称。另外,此处使用CTE是多余的SELECT-CTE下面的语句可能只是指定了原始表的名称。
STLDev '19

@STLDev实际上,STLDev不是枢轴如何工作的。我们不知道表“ pivot2”中的所有列。实际上,表中可能还有OP未指定的其他列。因此,除非您使用CTE或派生表查询来限制列,否则分组中将使用表中的所有列。换句话说,PIVOT返回的内容不是我们期望的。这是70-761认证考试中涵盖的概念。
Zorkolot

2
值得注意的是,PIVOT会自动根据PIVOT本身未使用的列进行分组。因此,在这个例子中[数据]和[dbcolumnname]在枢轴所以一切都将通过[客户]进行分组
萨尔

9
SELECT
main.CustomerID,
f.Data AS FirstName,
m.Data AS MiddleName,
l.Data AS LastName,
d.Data AS Date
FROM table main
INNER JOIN table f on f.CustomerID = main.CustomerID
INNER JOIN table m on m.CustomerID = main.CustomerID
INNER JOIN table l on l.CustomerID = main.CustomerID
INNER JOIN table d on d.CustomerID = main.CustomerID
WHERE f.DBColumnName = 'FirstName' 
AND m.DBColumnName = 'MiddleName' 
AND l.DBColumnName = 'LastName' 
AND d.DBColumnName = 'Date' 

编辑:我写了没有编辑器,并且没有运行SQL。希望您能明白。


9

好的,很抱歉这个问题。gbn让我步入正轨。这就是我一直在寻找的答案。

SELECT [FirstName], [MiddleName], [LastName], [Date] 
FROM #temp 
PIVOT
(   MIN([Data]) 
    FOR [DBColumnName] IN ([FirstName], [MiddleName], [LastName], [Date]) 
)AS p

然后,我不得不使用while语句并将上述语句构建为varchar并使用dynmaic sql。

使用这样的东西

SET @fullsql = @fullsql + 'SELECT ' + REPLACE(REPLACE(@fulltext,'(',''),')','')
SET @fullsql = @fullsql + 'FROM #temp '
SET @fullsql = @fullsql + 'PIVOT'
SET @fullsql = @fullsql + '('
SET @fullsql = @fullsql + ' MIN([Data])'
SET @fullsql = @fullsql + ' FOR [DBColumnName] IN '+@fulltext
SET @fullsql = @fullsql + ')'
SET @fullsql = @fullsql + 'AS p'

EXEC (@fullsql)

使用while循环构建@fulltext并从表中选择不同的列名称。感谢您的回答。


6

OP实际上并不需要在没有聚集的情况下进行数据透视,但是对于那些来这里的人来说,他们知道如何看待:

SQL参数化CTE查询

该问题的答案涉及一种情况,即需要不进行汇总的数据透视,因此,执行此操作的示例是解决方案的一部分。


1

试试这个:

SELECT CUSTOMER_ID, MAX(FIRSTNAME) AS FIRSTNAME, MAX(LASTNAME) AS LASTNAME ...

FROM
(

SELECT CUSTOMER_ID, 
       CASE WHEN DBCOLUMNNAME='FirstName' then DATA ELSE NULL END AS FIRSTNAME,
       CASE WHEN DBCOLUMNNAME='LastName' then DATA ELSE NULL END AS LASTNAME,
        ... and so on ...
GROUP BY CUSTOMER_ID

) TEMP

GROUP BY CUSTOMER_ID

1

这应该工作:

select * from (select [CustomerID]  ,[Demographic] ,[Data]
from [dbo].[pivot]
) as Ter

pivot (max(Data) for  Demographic in (FirstName, MiddleName, LastName, [Date]))as bro

1

这是为枢纽查询建立动态栏位的好方法:

-将值汇总到tmp表

declare @STR varchar(1000)
SELECT  @STr =  COALESCE(@STr +', ', '') 
+ QUOTENAME(DateRange) 
from (select distinct DateRange, ID from ##pivot)d order by ID

---查看生成的字段

print @STr

exec('  .... pivot code ...
pivot (avg(SalesAmt) for DateRange IN (' + @Str +')) AS P
order by Decile')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.