2009-08-27 15 views
92

Mam tabeli jak to ...TSQL Pivot bez zagregowanej funkcji

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 

I chcę to ...

Czy to możliwe przy użyciu 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 

Odpowiedz

77

Możesz użyć agregatu MAX, nadal będzie działać. MAX jednej wartości = ta wartość ..

W tym przypadku możesz również dołączyć do 5-krotnego połączenia z klientem, filtrować według dbColumnName dla każdego odwołania do tabeli. To może zadziałać lepiej.

+0

że faktycznie nie będzie działać, jeśli masz 2 costumers z tym samym imieniem – Leonardo

+0

który będzie działał. Pamiętaj, że DBColumnName to metadane - filtrujesz je dosłownie "CustomerID = 1 AND DBColumnName =" FirstName "".Oczywiście to się zepsuje, jeśli masz wiele wierszy FirstName dla danego ID klienta, ale jeśli poprawnie tworzysz tabele, zarówno identyfikator klienta, jak i nazwa_grupy_DBC, są częścią klucza podstawowego ... – 4AM

+0

@ Czy możesz podać kod, aby to zrobić? –

122

tak, ale dlaczego !! ??

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

^^ To działało dla mnie. PIVOT nie jest wydajny dla wartości nieliczbowych. – Dienekes

+3

Podoba mi się to. Pracował świetnie! – uotonyh

+3

To jest świetna alternatywa. Używałem 'Pivot' w moim zapytaniu, a następnie przerzuciłem się na to i przyjrzałem się planowi wykonania, aby uruchomić oba razem. Takie podejście kosztowało 8%, a podejście Pivot zajęło 92%! – mafue

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' 

Edit: Pisałem to bez edytora & nie uruchomić SQL. Mam nadzieję, że masz pomysł.

7

Ok, przepraszam za kiepskie pytanie. gbn postawił mnie na właściwej drodze. Tego właśnie szukałem w odpowiedzi.

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

Następnie musiałem użyć instrukcji while i skompilować powyższą instrukcję jako varchar i użyć dynmaic sql.

Korzystanie coś jak ten

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) 

mający budować @fulltext za pomocą pętli while i wybierz odrębne nazwy kolumn z tabeli. Dzięki za odpowiedzi.

5

PO faktycznie nie trzeba obracać bez agrégation ale dla tych z was przychodzi tu umieć zobaczyć:

sql parameterised cte query

Odpowiedź na to pytanie wiąże się z sytuacją, w której potrzebne jest obrotowa bez agregacji więc przykład wykonania tego jest częścią rozwiązania.

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

Spróbuj tego:

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

To powinno działać:

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

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

Oto świetny sposób na budowanie dynamicznych pól dla zapytania przegubu:

wartości --summarize do tabeli tmp

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

--- zobaczyć pola generowane

print @STr 

exec(' .... pivot code ... 
pivot (avg(SalesAmt) for DateRange IN (' + @Str +')) AS P 
order by Decile')