【问题标题】:Sum values from multiple tables grouping by a common column将多个表中的值按公共列分组
【发布时间】:2018-12-12 23:14:08
【问题描述】:

我在 MS SQL Server 2014 中有三个表。每个表都包含几个数值、一个描述和一个日期。为简洁起见,我们假设以下表格:

table "beverages"

day        beverage amount
---------- -------- ------
2018-12-01 water    2
2018-12-01 tea      1
2018-12-01 coffee   7
2018-12-02 water    4
2018-12-02 tea      2


table "meals"

day        meal   amount
---------- ------ ------
2018-12-01 burger 1
2018-12-01 bread  2
2018-12-02 steak  1


table "fruit"

day        fruit  amount
---------- ------ ------
2018-12-01 apple  4
2018-12-01 banana 1
2018-12-02 apple  2

然后我有另一个表只包含日期列表。

table "dates"

day
----------
2018-12-01
2018-12-02

我需要的是一个查询,它为dates 表中的每一行返回一行,每一行都有日期、饮料总量、膳食总量和水果总量为那一天。我不关心不同类型的饮料、膳食和水果,只关心总和。结果应该是:

expected result

day        beverages   meals       fruit
---------- ----------- ----------- -----------
2018-12-01 10          3           5
2018-12-02 6           1           2 

但是我收到了

received result

day        beverages   meals       fruit
---------- ----------- ----------- -----------
2018-12-01 40          18          30
2018-12-02 6           2           4

我已经知道问题出在哪里,只是不知道如何解决。更糟糕的是,我确信我曾经知道答案,但现在我什至无法找出正确的搜索词来让 Google 告诉我......

当我进行这样的查询时(我使用表变量进行测试)

SELECT 
     [d].[day]
    ,SUM([b].[amount]) AS [beverages]
    ,SUM([m].[amount]) AS [meals]
    ,SUM([f].[amount]) AS [fruit]
FROM @dates AS [d]
LEFT OUTER JOIN @beverages AS [b]
    ON [d].[day] = [b].[day]
LEFT OUTER JOIN @meals AS [m]
    ON [d].[day] = [m].[day]
LEFT OUTER JOIN @fruit AS [f]
    ON [d].[day] = [f].[day]
GROUP BY [d].[day]

它不止一次地对不同表中的每一行求和,因为它返回三个表的所有可能组合。删除 SUM() 和 GROUP BY 证明:

day        beverages   meals       fruit
---------- ----------- ----------- -----------
2018-12-01 2           1           4
2018-12-01 2           1           1
2018-12-01 2           2           4
2018-12-01 2           2           1
2018-12-01 1           1           4
2018-12-01 1           1           1
2018-12-01 1           2           4
2018-12-01 1           2           1
2018-12-01 7           1           4
2018-12-01 7           1           1
2018-12-01 7           2           4
2018-12-01 7           2           1
2018-12-02 4           1           2
2018-12-02 2           1           2

那么,我需要在查询中进行哪些更改,以使其对三个表中每个表的值求和,而不将其与其他表中的行数相乘?

【问题讨论】:

    标签: sql-server tsql join pivot aggregate


    【解决方案1】:

    在加入之前对表格进行分组,如下所示:

    SELECT 
         [d].[day]
        ,[b].[amount] AS [beverages]
        ,[m].[amount] AS [meals]
        ,[f].[amount] AS [fruit]
    FROM @dates AS [d]
    LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM @beverages GROUP BY day) AS [b]
        ON [d].[day] = [b].[day]
    LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM @meals GROUP BY day) AS [m]
        ON [d].[day] = [m].[day]
    LEFT OUTER JOIN (SELECT day, SUM(amount) as amount FROM @fruit GROUP BY day) AS [f]
        ON [d].[day] = [f].[day]
    

    【讨论】:

    • 谢谢...现在我读到了您的回答,我想知道我怎么可能忘记了这一点。你刚刚拯救了我的一天!
    【解决方案2】:

    改为 PIVOT 怎么样?

    示例

    Select *
     From (
            Select day,Item='beverage',amount from beverages
            Union All
            Select day,Item='meals'   ,amount from meals
            Union All
            Select day,Item='fruit'   ,amount from fruit
          ) src
    Pivot ( sum(amount) for Item in ([beverages],[meals],[fruit]) ) pvt
    

    【讨论】:

    • 还没有使用 PIVOT 查询,所以我选择了 Richard 的“加入前组”解决方案,但这绝对是我应该习惯的,因为它看起来更灵活。感谢您的回答!
    • @PatrickEchterbruch 我相信你会发现 PIVOT 总有一天会派上用场的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    相关资源
    最近更新 更多