Toplama fonksiyonu olmayan TSQL Pivot


139

Böyle bir masam var ...

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

Ve bunu istiyorum ...

PIVOT kullanarak bu mümkün müdür?

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

Yanıtlar:


102

MAX agregayı kullanabilirsiniz, yine de işe yarayacaktır. Bir değerin MAX değeri = bu değer ..

Bu durumda, customerid'de 5 kez kendi kendine katılabilir, tablo referansı başına dbColumnName'e göre filtreleyebilirsiniz. Daha iyi sonuç verebilir.


1
Aynı ada sahip 2 müşteri varsa bu işe yaramaz
Leonardo

1
İşe yarayacak. DBColumnName'in meta veri olduğunu unutmayın - kelimenin tam anlamıyla "CustomerID = 1 AND DBColumnName = 'FirstName'" ile filtrelersiniz. Tabii ki, bu sonları belirli bir CustomerID'deki için birden Ad satır varsa, ancak düzgün tablolar oluşturma eğer MüşteriNo ve DBColumnName hem ... birincil anahtarın parçası olan
04:00

7
Örnek olarak bazı kod / alay harika olurdu ve bu cevabı mükemmel bir şekilde tamamlardı.
DavidScherer

167

Evet ama neden !!??

   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
^^ Bu benim için çalıştı. PIVOT sayısal olmayan değerler için verimli değildir.
Dienekes

6
Bu harika bir alternatif. Sorgumda kullanıyordum Pivot, sonra buna geçtim ve ikisini birlikte çalıştırmak için yürütme planına baktım. Bu yaklaşım% 8 ve Pivot yaklaşımı% 92 aldı!
mafue

2
@CharlesBretana, harikasın! Ruhumu kurtardın! ) Bu en iyi çözüm. Teşekkürler!
Chaki_Black

3
Bu çözümü gerçekten çok seviyorum, ayrıca sütunların Pivot yerine doğru verileri içerdiğinden emin oluyor, teşekkürler!
Tenerezza

2
Bu iş harika! Ama nasıl Warning: Null value is eliminated by an aggregate or other SET operation
önlerim

24
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 komutunun doğru kullanımını gösterdiğinden bu kabul edilen cevap olmalıdır.
Ubercoder

1
Bu sorguda, "pivot2" nin orijinal verinin bulunduğu tablonun adı olduğunu belirtmek gerekir. Ayrıca, burada CTE kullanımı gereksizdir - SELECTCTE'nin altındaki ifade sadece orijinal tablonun adını belirtebilirdi.
STLDev

@STLDev Aslında STLDev, pivotun çalışma şekli bu değildir. "Pivot2" tablosundaki tüm sütunları bilmiyoruz. Aslında, OP'nin tabloda belirtmediği diğer sütunlar olabilir. Dolayısıyla, CTE veya Türetilmiş tablo sorgusu kullanarak sütunları kısıtlamadığınız sürece, gruplandırmada tablodaki TÜM sütunlar kullanılır. Başka bir deyişle, PIVOT bir şey döndürür ama beklediğimiz gibi değil. Bu, 70-761 sertifikasyon sınavı için derinlemesine ele alınan bir kavramdır.
Zorkolot

2
PIVOT'un PIVOT'un kendisinde kullanılmayan sütunlara göre otomatik olarak gruplandırdığını belirtmek gerekir. Dolayısıyla bu örnekte [data] ve [dbcolumnname] PIVOT'ta yer almaktadır, bu nedenle her şey [CustomerId] tarafından gruplandırılacaktır
Sal

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' 

Düzenleme: Bu bir editör olmadan yazdım ve SQL çalıştırmadı. Umarım, fikri anlarsın.


9

Tamam, zavallı soru için özür dilerim. gbn beni doğru yola soktu. Bir cevapta aradığım şey buydu.

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

Sonra bir while deyimi kullanmak ve yukarıdaki deyimi bir varchar olarak oluşturmak ve dinamik sql kullanmak zorunda kaldı.

Bunun gibi bir şey kullanmak

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 döngüsü kullanarak @fulltext oluşturmak ve tablodan farklı sütun adlarını seçmek. Cevaplar için teşekkürler.


6

OP'nin anlaşmadan gerçekte pivot yapmasına gerek yoktu, ama buraya gelenlerin nasıl göreceğini bilmesi:

sql parametreli cte sorgusu

Bu sorunun cevabı, toplanmasız pivotun gerekli olduğu bir durumu içerir, bu yüzden bunu yapmanın bir örneği çözümün bir parçasıdır.


1

Bunu dene:

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

Bu çalışmalı:

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

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

1

Bir pivot sorgusu için dinamik alanlar oluşturmanın harika bir yolu:

- değerleri bir tmp tablosuyla özetleme

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

--- oluşturulan alanlara bakın

print @STr

exec('  .... pivot code ...
pivot (avg(SalesAmt) for DateRange IN (' + @Str +')) AS P
order by Decile')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.