2009-08-27 24 views
92

Tengo una tabla como esta ...TSQL pivote sin función agregada

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 

Y quiero esto ...

Es esto posible utilizar 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 

Respuesta

77

Puede usar el agregado MAX, aún así funcionaría. MAX de un valor = ese valor ..

En este caso, también podría unirse a sí mismo 5 veces en customerid, filtrar por dbColumnName por referencia de tabla. Puede funcionar mejor.

+0

que realmente no trabajará si usted tiene 2 clientes con el mismo nombre – Leonardo

+0

que funcionará. Recuerde que DBColumnName es metadata: usted literalmente filtra por "CustomerID = 1 AND DBColumnName = 'FirstName'".Por supuesto, esto se rompe si tiene varias filas de FirstName para un CustomerID determinado, pero si está creando correctamente sus tablas, tanto CustomerID como DBColumnName son parte de su clave principal ... – 4AM

+0

@ ¿Podría proporcionar algún código para hacerlo, por favor? –

122

sí, pero ¿por qué? ??

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

^^ Esto funcionó para mí. PIVOT no es eficiente para valores no numéricos. – Dienekes

+3

Me gusta esto. Funcionó muy bien! – uotonyh

+3

Esta es una gran alternativa. Estaba usando 'Pivot' en mi consulta, luego cambié a esto y miré el plan de ejecución para ejecutar ambos juntos. ¡Este enfoque costó 8% y el enfoque Pivot tomó 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' 

Edición: He escrito esto sin un editor & no ha ejecutado el SQL. Espero que captes la idea.

7

Bien, disculpe la pobre pregunta. gbn me puso en el camino correcto. Esto es lo que estaba buscando en una respuesta.

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

Luego tuve que utilizar una sentencia while y construir la declaración anterior como varchar y utilizar SQL dynmaic.

Usando algo como esto

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) 

Tener un @fulltext construir usando un bucle while y seleccione los nombres de las columnas distintas de la tabla. Gracias por las respuestas.

5

El PO en realidad no tiene que girar sin agregación, pero para aquellos de ustedes que viene aquí para saber cómo ver:

sql parameterised cte query

La respuesta a esa pregunta implica una situación en la que se necesita de pivote sin agregación así que un ejemplo de hacerlo es parte de la solución.

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

Prueba esto:

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

esto debería funcionar:

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

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

Aquí es una gran manera de construir campos dinámicos para una consulta de pivote:

valores --summarize a una tabla tmp

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

--- ver los campos generados

print @STr 

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