【问题标题】:How to SUM columns on multiple conditions in a GROUP BY如何在 GROUP BY 中对多个条件的列求和
【发布时间】:2011-02-14 17:53:28
【问题描述】:

我正在尝试返回包含余额、结果和收入的帐户列表

Account            Transaction
-------            -----------
AccountID          TransactionID
BankName           AccountID
Locale             Amount
Status

这是我目前拥有的。有人可以解释我哪里出错了吗?

select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.STATUS,
    sum(t1.AMOUNT) as BALANCE,
    sum(t2.AMOUNT) as OUTCOME,
    sum(t3.AMOUNT) as INCOME
from ACCOUNT a
left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID
left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID and t2.AMOUNT < 0
left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID and t3.AMOUNT > 0
group by a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

更新

已根据下面的评论更正了 t2 左连接语法。

希望从问题中可以明显看出我期望的输出。对于 6 个帐户,SQL 应返回 6 个帐户及其余额、收入和结果。

我提供的 SQL 的问题是数字错误!根据 cmets,我认为问题源于多次加入,这导致金额的总和不正确。

【问题讨论】:

  • 不应该像 t2.ACCOUNT_ID = a.ACCOUNT_ID 那样在 t2 上加入 TRANSACTION t2 吗? {请编辑问题。从下面 Neil Moss 的回答中提升为评论}

标签: sql tsql group-by


【解决方案1】:

由于您没有告诉我们what's going wrong(也就是说,除了描述您期望的行为之外,还描述了您得到的行为),很难说在哪里,但有两种可能性。尼尔指出了一个。另一个是由于您在事务表上加入了 3 次,因此您将事务与事务配对并获得重复。相反,只需在事务表上加入一次,然后更改对 Amount 列的汇总方式。

Select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.STATUS,
    sum(t.AMOUNT) as BALANCE,
    sum((t.AMOUNT < 0) * t.AMOUNT) As OUTGOING,
    sum((t.AMOUNT > 0) * t.AMOUNT) As INCOMING
From ACCOUNT a
Left Join TRANSACTION t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

您可以使用CASE 表达式作为乘法的更易读的替代方案:

Select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.[STATUS],
    sum(t.AMOUNT) As BALANCE,
    sum(CASE WHEN t.AMOUNT < 0 THEN t.AMOUNT ELSE 0 end) As OUTCOME,
    sum(CASE WHEN t.AMOUNT > 0 THEN t.AMOUNT ELSE 0 end) As INCOME
From ACCOUNT a
Left Join [TRANSACTION] t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

【讨论】:

  • @outis - AFAIK,t-sql 没有 LEAST 也没有 GREATEST 函数。
  • @Thomas:好吧,这很糟糕。更改为不使用它们。
  • 在我的问题中提供了最终答案。接受了您的答案,但使用 SUM(CASE WHEN... 作为 OUTCOME 和 INCOME 值。
【解决方案2】:

你的意思是:

select 
    a.ACCOUNT_ID, 
    a.BANK_NAME, 
    a.LOCALE, 
    a.STATUS, 
    sum(t1.AMOUNT) as BALANCE, 
    sum(CASE WHEN t2.AMOUNT < 0 THEN t2.Amount ELSE 0 END) as OUTCOME, 
    sum(CASE WHEN t3.AMOUNT > 0 THEN t3.Amount ELSE 0 END) as INCOME 
from 
    ACCOUNT a 
    left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID 
    left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID
    left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID
group by 
    a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS] 

【讨论】:

  • 只是缺少 CASE 语句中的 END。
  • 赞成但不能接受答案,因为我的问题对结果含糊不清,应该只加入交易表一次。
【解决方案3】:

我不确定您为什么需要多个连接。你不能简单地做这样的事情:

Select
    a.ACCOUNT_ID
    , a.BANK_NAME
    , a.LOCALE
    , a.STATUS
    , Sum ( t.Amount ) As Balance
    , Sum( Case When t.Amount < 0 Then Amount End ) As Outcome
    , Sum( Case When t.Amount > 0 Then Amount End ) As Income
From ACCOUNT a
    Left Join TRANSACTION t 
        On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

【讨论】:

    【解决方案4】:

    TRANSACTION t2 的连接应该在 在 t2 上,如 on t2.ACCOUNT_ID = a.ACCOUNT_ID

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      • 2022-07-22
      • 2021-02-14
      • 1970-01-01
      • 2016-09-06
      • 1970-01-01
      • 2012-10-07
      相关资源
      最近更新 更多