2012-05-03 16 views
29

Soy muy nuevo en SQL.Comprender la función PIVOT en T-SQL

Tengo una tabla como la siguiente:

ID | TeamID | UserID | ElementID | PhaseID | Effort 
----------------------------------------------------- 
1 | 1 | 1  | 3  | 5  | 6.74 
2 | 1 | 1  | 3  | 6  | 8.25 
3 | 1 | 1  | 4  | 1  | 2.23 
4 | 1 | 1  | 4  | 5  | 6.8 
5 | 1 | 1  | 4  | 6  | 1.5 

y me dijeron que para obtener datos como éste

ElementID | PhaseID1 | PhaseID5 | PhaseID6 
-------------------------------------------- 
    3  | NULL | 6.74 | 8.25 
    4  | 2.23 | 6.8 | 1.5 

entiendo que necesito para usar la función de pivote. Pero no puedo entenderlo claramente. Sería de gran ayuda si alguien puede explicarlo en el caso anterior. (O cualquiera de las alternativas, si las hubiera)

Respuesta

40

A PIVOT usado para rotar los datos de una columna en múltiples columnas.

Para su ejemplo aquí es un pivote estática que significa codificar las columnas que desea rotar:

create table temp 
(
    id int, 
    teamid int, 
    userid int, 
    elementid int, 
    phaseid int, 
    effort decimal(10, 5) 
) 

insert into temp values (1,1,1,3,5,6.74) 
insert into temp values (2,1,1,3,6,8.25) 
insert into temp values (3,1,1,4,1,2.23) 
insert into temp values (4,1,1,4,5,6.8) 
insert into temp values (5,1,1,4,6,1.5) 

select elementid 
    , [1] as phaseid1 
    , [5] as phaseid5 
    , [6] as phaseid6 
from 
(
    select elementid, phaseid, effort 
    from temp 
) x 
pivot 
(
    max(effort) 
    for phaseid in([1], [5], [6]) 
)p 

Aquí es una SQL Demo con una versión de trabajo.

Esto también se puede hacer a través de un PIVOT dinámico donde crea dinámicamente la lista de columnas y realiza el PIVOTE.

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX); 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.phaseid) 
      FROM temp c 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT elementid, ' + @cols + ' from 
      (
       select elementid, phaseid, effort 
       from temp 
      ) x 
      pivot 
      (
       max(effort) 
       for phaseid in (' + @cols + ') 
      ) p ' 


execute(@query) 

Los resultados para ambos:

ELEMENTID PHASEID1 PHASEID5 PHASEID6 
3   Null  6.74  8.25 
4   2.23  6.8   1.5 
+1

Gracias lo tengo. Lo único que necesito es codificar 'PhaseID' antes de QUOTENAME. ¿derecho? –

+1

en el QUOTENAME debe identificar de qué columna necesita obtener los valores.¿Es eso lo que preguntas? – Taryn

+2

bien. Lo tengo. Gracias –

5

Estos son los ejemplos de pivote muy básicos.

SQL SERVER – PIVOT and UNPIVOT Table Examples

Ejemplo desde arriba enlace para la tabla de productos:

SELECT PRODUCT, FRED, KATE 
FROM (
SELECT CUST, PRODUCT, QTY 
FROM Product) up 
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt 
ORDER BY PRODUCT 

hace:

PRODUCT FRED KATE 
-------------------- 
BEER  24 12 
MILK  3  1 
SODA NULL  6 
VEG NULL  5 

ejemplos similares se pueden encontrar en la entrada de blog Pivot tables in SQL Server. A simple sample

+1

realmente simple ejemplo. Gracias :) –

2

Para establecer error de compatibilidad

uso esto antes de usar la función de pivote

ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 100 
0
SELECT <non-pivoted column>, 
    [first pivoted column] AS <column name>, 
    [second pivoted column] AS <column name>, 
    ... 
    [last pivoted column] AS <column name> 
FROM 
    (<SELECT query that produces the data>) 
    AS <alias for the source query> 
PIVOT 
(
    <aggregation function>(<column being aggregated>) 
FOR 
[<column that contains the values that will become column headers>] 
    IN ([first pivoted column], [second pivoted column], 
    ... [last pivoted column]) 
) AS <alias for the pivot table> 
<optional ORDER BY clause>; 

USE AdventureWorks2008R2 ; 
GO 
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost 
FROM Production.Product 
GROUP BY DaysToManufacture; 

    DaysToManufacture   AverageCost 
0       5.0885 
1       223.88 
2       359.1082 
4       949.4105 

    -- Pivot table with one row and five columns 
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days, 
[0], [1], [2], [3], [4] 
FROM 
(SELECT DaysToManufacture, StandardCost 
    FROM Production.Product) AS SourceTable 
PIVOT 
(
AVG(StandardCost) 
FOR DaysToManufacture IN ([0], [1], [2], [3], [4]) 
) AS PivotTable; 




Here is the result set. 
Cost_Sorted_By_Production_Days 0   1   2   3  4  
AverageCost      5.0885 223.88 359.1082 NULL 949.4105 
2

yo era nuevo en esto y yo crea una buena publicación al respecto ... Mi problema m fue entender cómo aplicar correctamente la agregación y aquí está mi mensaje: http://jaider.net/posts/1176-pivot-in-sql-server-correct-aggregated-results/

En solución @bluefeet, Es importante mencionar que elementid es la columna clave de su "invisible" Group By. Además, puede reemplazar elementid o agregar más columnas como userid.

enter image description here