Pregunta SQL Server - Tratando de des-normalizar mi tabla


Disculpas por el título, pero estoy tratando de hacer cosas muy por encima de mi nivel incluso para que lo explique.

Digamos que tengo una tabla con las variables persona, producto alimenticio y cantidad:

 Person  food     Amount
 Mike    Butter   3
 Mike    Milk     4
 Mike    Chicken  2
 Tim     Milk     4
 John    Chicken  2

Al unirme a la tabla consigo mismo en la consulta, he logrado hacer una lista donde la comida es la base de nuevas variables y el valor es la cantidad. La tabla anterior se convertiría en:

Person  Butter Milk Chicken
Mike    3      4    2

El código es aproximadamente:

Select 
    a.person, 
    b.amount as Butter,
    c.amount as Milk, 
    d.amount as Chicken
from PersonFoodAmount a
inner join PersonFoodAmount b on a.person = b.person
inner join PersonFoodAmount c on a.person=c.person
where b.food='Butter' 
and c.food='Milk'
and d.food='Chicken'

Ahora, esto me da a Mike porque marca todas las casillas. Pero también necesito tener las coincidencias parciales:

Person  Butter Milk Chicken
Mike    3      4    2
Tim     NULL   4    NULL
John    NULL   Null 2

He intentado todo tipo de combinaciones, incluida la combinación externa completa, pero todavía recibo personas con una nevera completa.

¿Alguna sugerencia?


5
2017-08-28 13:20


origen


Respuestas:


Puedes usar Pivot para hacer esto.

DECLARE @PersonStuff TABLE (Person varchar(10), Food varchar(10), Amount INT)

INSERT INTO @PersonStuff VALUES
('Mike','Butter', 3),
('Mike','Milk', 4),
('Mike','Chicken', 2),
('Tim','Milk', 4),
('John','Chicken', 2)

SELECT 
    * 
FROM ( 
    SELECT 
        * 
    FROM @PersonStuff ) AS SourceTable
PIVOT ( 
    AVG(Amount) 
    FOR Food IN ( [Butter],[Milk],[Chicken] ) 
) AS PivotTable

Resultado:

Person  Butter  Milk    Chicken
John    NULL    NULL    2
Mike    3       4       2
Tim     NULL    4       NULL

6
2017-08-28 13:42



Sugeriría algo mejor, agregación condicional:

SELECT t.person,
       MAX(CASE WHEN t.food = 'Butter' THEN t.amout END) as Butter,
       MAX(CASE WHEN t.food = 'Milk' THEN t.amout END) as Milk,
       MAX(CASE WHEN t.food = 'Chicken' THEN t.amout END) as Chicken
FROM PersonFoodAmount t
GROUP BY t.person

De esa manera, no tiene que unirse a la mesa 3 veces para sí mismo. Además, me resulta mucho más fácil leer este escrito una vez para entenderlo.


5
2017-08-28 13:25