2009-08-27 4 views
92

У меня есть таблица вроде этого ...TSQL Pivot без агрегатной функции

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, он все равно будет работать. MAX одного значения = это значение.

В этом случае вы также можете подключиться 5 раз к customerid, фильтровать по dbColumnName для ссылки на таблицу. Это может работать лучше.

+0

, что на самом деле не будет работать, если у вас есть 2 костюмеров с тем же именем – Leonardo

+0

Это будет работать. Помните, что DBColumnName - это метаданные - вы буквально фильтруете «CustomerID = 1 AND DBColumnName =« FirstName »».Конечно, это прерывается, если у вас есть несколько строк FirstName для данного CustomerID, но если вы правильно создаете свои таблицы, как CustomerID, так и DBColumnName являются частью вашего основного ключа ... – 4AM

+0

@ Не могли бы вы предоставить какой-то код для этого? –

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

+3

Мне это нравится. Отлично! – uotonyh

+3

Это отличная альтернатива. Я использовал «Pivot» в своем запросе, затем переключился на это и посмотрел план выполнения для совместной работы. Этот подход стоит 8%, а подход Pivot - 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: я написал это без редактора & не запустить SQL. Надеюсь, вы поняли эту идею.

7

Хорошо, извините за бедный вопрос. 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 '[email protected] 
SET @fullsql = @fullsql + ')' 
SET @fullsql = @fullsql + 'AS p' 

EXEC (@fullsql) 

Имея построить @fulltext используя время цикла и выбрать различные имена столбцов из таблицы. Спасибо за ответы.

5

ОП фактически не должны вращаться без агрегации, но и для тех из вас приходит сюда, чтобы узнать, как посмотреть:

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') 
Смежные вопросы