2009-08-27 141 views
92

我有一個這樣的表...TSQL樞軸沒有聚合函數

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 

回答

77

您可以使用MAX聚合,它仍然可以工作。一個值的最大值=該值。

在這種情況下,您也可以在customerid上自我加入5次,按dbColumnName的每個表引用進行篩選。它可能會更好。

+0

如果你有2周的costumers用相同的名字 – Leonardo 2015-02-20 18:38:21

+0

,將工作,實際上不會工作。請記住,DBColumnName是元數據 - 您可以按字面過濾「CustomerID = 1 AND DBColumnName ='FirstName'」。當然,如果你有一個給定的CustomerID有多個FirstName行,但是如果你正確地創建你的表,那麼CustomerID和DBColumnName都是你主鍵的一部分...... – 4AM 2016-06-01 15:51:18

+0

@你能提供一些代碼嗎? – 2017-06-28 03:52:24

122

是的,但爲什麼!! ??

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 
+1

^^這對我有用。 PIVOT不適用於非數字值。 – Dienekes 2010-08-25 09:49:34

+3

我喜歡這個。工作很棒! – uotonyh 2010-12-13 22:40:14

+3

這是一個很好的選擇。我在查詢中使用了'Pivot',然後我切換到了這個目錄,並查看了一起運行的執行計劃。這種方法的成本爲8%,透視方法的成本爲92%! – mafue 2012-04-24 19:44:58

5
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。我希望,你明白了。

7

好的,對不起,這個可憐的問題。 gbn讓我走上了正軌。 這就是我在尋找答案。

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

然後,我不得不使用while語句並將上述語句構建爲varchar並使用動態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 '[email protected] 
SET @fullsql = @fullsql + ')' 
SET @fullsql = @fullsql + 'AS p' 

EXEC (@fullsql) 

有一個建立@fulltext使用while循環,並選擇不同的列名出表的。感謝您的答案。

5

的OP實際上並沒有需要,而不agregation但對於那些你來這裏樞要懂得看:

sql parameterised cte query

的問題的答案涉及在需要無聚集支點的情況所以這樣做的一個例子是解決方案的一部分。

4
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; 
0

試試這個:

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 
0

這應該工作:

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

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

這裏是構建樞軸動態查詢領域的好方法:

--summarize值到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')