涉及SUM,LEFT JOIN和GROUP BY的复制

时间:2013-09-23 15:05:19

标签: mysql sql

我遇到涉及SUM,LEFT OUTER JOIN和GROUP BY命令的问题,但无法弄清楚我的错误在哪里。

我有两个表,一个用于客户交易,一个用于客户索赔。客户可以拥有多个交易和多个索赔,但在两个表中,行都是唯一的。客户也可以没有索赔。

交易表示例:

Transactions:
Customer | Transaction Year | Amount
-------------------------------------
A        | 2007             | 100
A        | 2008             | 80
A        | 2008             | 50
A        | 2009             | 210

索赔表示例:

Claims:
Customer | Claim Year | Amount
-------------------------------
A        | 2007       | 30
A        | 2007       | 40
A        | 2009       | 110

所需的输出是对两个金额求和,并为每个客户和年份的唯一组合生成一行。

Desired Output:
Customer | Year | Transaction Amount | Claim Amount
----------------------------------------------------
A        | 2007 | 100                | 70
A        | 2008 | 130                | NULL
A        | 2009 | 210                | 110

我使用了一个带有GROUP BY命令的LEFT OUTER JOIN命令作为Customer和Year值。但我得到的是Transaction Amount值的重复,并且倍数与Claims表中匹配行的数量有关。

因此,使用我的示例数据,我得到以下内容:

Actual Output:
Customer | Year | Transaction Amount | Claim Amount
----------------------------------------------------
A        | 2007 | 200                | 70
A        | 2008 | 130                | NULL
A        | 2009 | 210                | 110

在2007年,有两个声明导致Transactions.Amount值乘以2(当有三个声明时,Transaction.Amount三倍,等等。)

我的代码如下:

SELECT Transactions.Customer,
   Transactions.Year,
   sum(Transactions.Transaction Amount),
   sum(Claims.Claim Amount)
FROM Transactions
   LEFT JOIN Claims ON Claims.Customer = Transactions.Customer
      AND Transactions.Year = Claims.Year
GROUP BY Transactions.Customer, Transactions.Year

答案是否在子查询中?我不熟悉它们,所以任何指针都会很棒。感谢。

3 个答案:

答案 0 :(得分:4)

因此,查看正在发生的事情的第一步是删除SUM,只需选择交易金额和索赔金额。这样您就可以看到返回的数据。您将看到A / 2007上的联接将具有两次交易金额,因为它将每一行都连接到索赔表。

一种解决方案是使用subquerys,就像你说的那样,在加入之前单独进行SUM。

SELECT 
   Transactions.Customer,
   Transactions.Year,
   SumTransaction,
   SumClaim
FROM (
      select Customer, Year, sum(Transaction Amount) SumTransaction 
      from Transactions
      group by Customer, Year
   ) Transactions
   LEFT JOIN (
      select Customer, Year, sum(Claim Amount) sumClaim 
      from Claims
      group by Customer, Year
   ) Claims
   ON Claims.Customer = Transactions.Customer
      AND Transactions.Year = Claims.Year

根据您的限制,另一种可能的解决方案:

SELECT 
   Transactions.Customer,
   Transactions.Year,
   SUM(Transaction Amount),
   (SELECT SUM(Claim Amount) from Claims where Claims.Customer = Transactions.Customer and Claims.Year = Transactions.Year)
FROM 
   Transactions
GROUP BY
   Customer, Year

第三种可能的解决方案!!这个不需要任何子查询!见SQL Fiddle

select
    t.Customer,
    t.Year,
    sum(distinct t.Amount),
    sum(c.Amount)
from
    Transactions t
    left join Claims c
        on  t.Customer = c.Customer
            and t.Year = c.year
group by
    t.Customer,
    t.Year

答案 1 :(得分:0)

由于您有两项索赔,查询将在2007年两次计算交易金额,因此交易金额将被计算两次。

即。使用的返回数据是:

Customer | Transaction Year | Transaction Amount | Claim Amount
----------------------------------------------------------------
A        | 2007             | 100                | 30
A        | 2007             | 100                | 40
A        | 2008             | 80                 |
A        | 2008             | 50                 |
A        | 2009             | 210                | 110

如下所示,虽然不是很漂亮,但应解决问题:

SELECT 
   t.Customer
   ,t.Year
   ,[Transaction Amount] = SUM(t.[Transaction Amount])
   ,[Claim Amount] = c.[Claim Amount]
FROM 
    Transactions t
    LEFT JOIN (
        SELECT 
            Customer
            ,Year
            ,SUM([Claim Amount])
        FROM
           Claims
        GROUP BY
           Customer, Year
    ) c ON c.Customer = t.Customer c.Year = t.Year
GROUP BY t.Customer, t.Year, c.[Claim Amount]

答案 2 :(得分:-1)

With T as (
    SELECT  Customer,
            [Transaction Year],
            sum(Amount) AS TransactionAmount
    FROM Transactions
    GROUP BY Customer, [Transaction Year]
), C AS 
    SELECT  Customer,
            [Claim Year],
            sum(Amount) as ClaimAmount
    FROM Claims
    GROUP BY Customer, [Claim Year]
)
SELECT  T.Customer,
        [Transactions Year],
        TransactionAmount,
        ClaimAmount
FROM    T
   LEFT JOIN C ON C.Customer = T.Customer
      AND [Transactions Year] = [Claim Year]