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

Відповіді:


102

Можна використовувати агрегат MAX, він все одно буде працювати. MAX одного значення = це значення ..

У цьому випадку ви також можете самостійно приєднатись до клієнта 5 разів, фільтруючи за dbColumnName за посиланням на таблицю. Це може вийти краще.


1
що насправді не буде працювати, якщо у вас є 2 покупці з таким самим іменем
Леонардо

1
Це спрацює. Пам'ятайте, що DBColumnName є метаданими - ви буквально фільтруєте за "CustomerID = 1 AND DBColumnName =" FirstName "". Звичайно, ця помилка може мати місце, якщо у вас є кілька рядків FirstName для даного CustomerID, але якщо ви правильно створюєте таблиці, і CustomerID, і DBColumnName є частиною вашого основного ключа ...
4:00

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 не ефективний для нечислових значень.
Дінекес

6
Це чудова альтернатива. Я використовував Pivotу своєму запиті, потім перейшов до цього і переглянув план виконання обох разом. Цей підхід коштував 8%, а підхід Pivot - 92%!
мафу

2
@CharlesBretana, ти чудово! Ти врятував мою душу! ) Це найкраще рішення. Дякую!
Chaki_Black

3
Дуже подобається це рішення, також він гарантує, що стовпці містять правильні дані замість зведеного, дякую!
Тенереца

2
Ця робота чудова! Але як мені запобігти -Warning: Null value is eliminated by an aggregate or other SET operation
GiddyUpHorsey

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.
Ubercoder

1
Варто зазначити, що в цьому запиті "pivot2" - це назва таблиці, в якій знаходяться вихідні дані. Крім того, використання CTE тут є зайвим - SELECTзаява нижче CTE могла просто вказати назву вихідної таблиці.
СТЛДєв

@STLDev Насправді STLDev це не так, як працює півот. Ми не знаємо всіх стовпців таблиці "pivot2". Насправді, можуть бути й інші стовпці. ОП не вказали, які є в таблиці. Отже, якщо ви не обмежуєте стовпці - використовуючи CTE або Похідний запит таблиці - тоді ВСЕ стовпці таблиці використовуються в групуванні. Іншими словами, PIVOT повертає щось, але не те, що ми очікуємо. Це поглиблене поняття для сертифікаційного іспиту 70-761.
Zorkolot

2
Варто зазначити, що PIVOT автоматично групується за будь-якими стовпцями, які не використовуються в самому PIVOT. Тож у цьому прикладі [дані] та [ім'я dbcolumn] є у PIVOT, тому все буде згруповано за [CustomerId]
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' 

Редагувати: Я написав це без редактора і не запустив SQL. Я сподіваюся, ви зрозуміли ідею.


9

Гаразд, вибачте за бідне питання. gbn привів мене до правильного шляху. Це я шукав у відповіді.

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

Тоді мені довелося використовувати оператор час і будувати вищезазначений оператор як 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)

Маючи побудувати @fulltext, використовуючи цикл while, і виберіть окремі назви стовпців із таблиці. Дякую за відповіді.


6

Оперативній програмі насправді не потрібно було погоджуватися без узгодження, але для тих, хто ви приїжджаєте сюди, щоб знати, як бачити:

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')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.