SQL Server - 尝试对我的表进行反规范化

use*_*167 5 sql sql-server join

为标题道歉,但我正试图在我的水平之上做一些事情甚至让我解释它.

假设我有一个包含变量person,foodstuff和amount的表:

 Person  food     Amount
 Mike    Butter   3
 Mike    Milk     4
 Mike    Chicken  2
 Tim     Milk     4
 John    Chicken  2
Run Code Online (Sandbox Code Playgroud)

通过在查询中将表连接到自身,我已设法创建一个列表,其中食物是新变量的基础,值是金额.上表将成为:

Person  Butter Milk Chicken
Mike    3      4    2
Run Code Online (Sandbox Code Playgroud)

代码大约是:

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'
Run Code Online (Sandbox Code Playgroud)

现在,这给了迈克,因为他检查了所有的盒子.但我还需要部分匹配:

Person  Butter Milk Chicken
Mike    3      4    2
Tim     NULL   4    NULL
John    NULL   Null 2
Run Code Online (Sandbox Code Playgroud)

我尝试了各种连接,包括全外连接,但我仍然只能让人满载冰箱.

有什么建议?

Ser*_*lan 6

您可以使用Pivot进行此操作.

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
Run Code Online (Sandbox Code Playgroud)

结果:

Person  Butter  Milk    Chicken
John    NULL    NULL    2
Mike    3       4       2
Tim     NULL    4       NULL
Run Code Online (Sandbox Code Playgroud)


sag*_*agi 5

我会建议更好的条件聚合:

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
Run Code Online (Sandbox Code Playgroud)

这样,您不必将表连接3次.此外,我发现这篇文章更容易阅读一次以理解它.