2012-08-31 15 views
16

autorización I tiene una tabla que tiene este aspectoT-SQL cruzada dinámica

ItemID | ColumnName | Value 
1  | name  | Peter 
1  | phone  | 12345678 
1  | email  | [email protected] 
2  | name  | John 
2  | phone  | 87654321 
2  | email  | [email protected] 
3  | name  | Sarah 
3  | phone  | 55667788 
3  | email  | [email protected] 

ahora tengo que convertir eso en esto:

ItemID | name | phone | email 
1  | Peter | 12345678 | [email protected] 
2  | John | 87654321 | [email protected] 
3  | Sarah | 55667788 | [email protected] 

He estado buscando en ejemplos de pivote dinámicos, pero parece que no soy capaz de encajarlos en mi escenario.

¿Alguien puede ayudar?

+0

no veo un pivote en sus datos. Ha enumerado los nombres y valores de columnas regulares de una manera extraña en el primer bloque, y normalmente en el segundo. – IamIC

+0

Y si el primer bloque representa sus datos reales, ¿por qué está almacenado así en lugar de normalizado? – IamIC

+0

¿Por qué necesita un PIVOT dinámico para esta información? Esto se puede lograr con un PIVOT estático (verifique mi respuesta). ¿Es porque espera que ColumnName tenga valores distintos al nombre, el teléfono y el correo electrónico? – Kash

Respuesta

26

Tenga una mirada en el ejemplo

CREATE TABLE #Table (
     ID INT, 
     ColumnName VARCHAR(250), 
     Value VARCHAR(250) 
) 

INSERT INTO #Table SELECT 1,'name','Peter' 
INSERT INTO #Table SELECT 1,'phone','12345678' 
INSERT INTO #Table SELECT 1,'email','[email protected]' 
INSERT INTO #Table SELECT 2,'name','John' 
INSERT INTO #Table SELECT 2,'phone','87654321' 
INSERT INTO #Table SELECT 2,'email','[email protected]' 
INSERT INTO #Table SELECT 3,'name','Sarah' 
INSERT INTO #Table SELECT 3,'phone','55667788' 
INSERT INTO #Table SELECT 3,'email','[email protected]' 

---I assumed your tablename as TESTTABLE--- 
DECLARE @cols NVARCHAR(2000) 
DECLARE @query NVARCHAR(4000) 

SELECT @cols = STUFF((SELECT DISTINCT TOP 100 PERCENT 
           '],[' + t.ColumnName 
         FROM #Table AS t 
         --ORDER BY '],[' + t.ID 
         FOR XML PATH('') 
        ), 1, 2, '') + ']' 

SELECT @cols 

SET @query = N'SELECT ID,'+ @cols +' FROM 
(SELECT t1.ID,t1.ColumnName , t1.Value FROM #Table AS t1) p 
PIVOT (MAX([Value]) FOR ColumnName IN ('+ @cols +')) 
AS pvt;' 

EXECUTE(@query) 

DROP TABLE #Table 
+0

¡Muchas gracias, eso era exactamente lo que estaba buscando! –

+0

¡Funciona muy bien! :) –

-1

Esto es una consulta que estoy usando para mi lista de contactos :)

SELECT * 
FROM 
    (
    SELECT Contact_Id AS CT 
      , [Age] 
      , [Sex] 
      , [State] 
      , [Country] 
      , [Keyword] 
      , [Married] 
      , [Kids] 
      , [Car] 
    FROM 
     (SELECT c.PropertyName 
       , c.ValueString 
       , c.Contact_Id 
      FROM 
       ContactProfiles c) AS ctp 
     PIVOT (max(ctp.ValueString) FOR PropertyName IN ([Age], [Sex], [State], [Country], [Keyword], [Married], [Kids], [Car])) AS PivotTable 
     ) AS pvt 

WHERE 
    pvt.[Age] > 18 
    AND (pvt.[State] = 'CA' OR pvt.[State] = 'NY') 
    AND pvt.[Sex] = 'F' 
    --*AND pvt.[Keyword] LIKE '%B;%' 
    AND pvt.[Married] = 'True' 
    AND pvt.[Kids] > 0 
0

siguiente No es necesario cruzada dinámica, becuase que será una mesa diferente Basta con hacer algo como esto:

name phone email 
--------------------------------- 
Peter    
     123456 
       [email protected] 

Marque esta SQL fiddle

SELECT DISTINCT u.ItemID, n.Value as 'name', p.Value as 'phone', e.Value as 'email' 
FROM UserData u 
INNER JOIN(
SELECT ItemID, Value 
FROM UserData WHERE ColumnName = 'name') n ON n.ItemID = u.ItemID 
INNER JOIN(
SELECT ItemID, Value 
FROM UserData WHERE ColumnName = 'phone') p ON p.ItemID = u.ItemID 
INNER JOIN(
SELECT ItemID, Value 
FROM UserData WHERE ColumnName = 'email') e ON e.ItemID = u.ItemID 
+2

El problema es que los ColumnNames son dinámicos. Tanto sus nombres como el número de columnas serán diferentes. –

3

intente esto:

SQL Server 2005+

;with 
     cte_name as(select * from <table> where ColumnName='name'), 
     cte_phone as(select * from <table> where ColumnName='phone'), 
     cte_email as(select * from <table> where ColumnName='email') 
    select n.ItemID,n.Value [Name],p.Value [Phone],e.Value [Email] 
    from cte_name n 
    join cte_phone p 
    on n.ItemID=p.ItemID 
    join cte_email e 
    on n.ItemID=e.ItemID 


SQL Fiddle Demo

-1

Has probado esto:

SELECT ItemID, name, phone, email 
FROM 
(SELECT [ItemID] ,[ColumnName] ,[Value] FROM Item) Item 
PIVOT (MAX(Value) FOR ColumnName IN (name, phone, email)) as pvt 
+2

El problema es que los ColumnNames son dinámicos. Tanto sus nombres como el número de columnas serán diferentes. –