如何根据聚合中的其余行从聚合中排除行

时间:2015-12-22 14:55:17

标签: sql-server tsql sql-server-2012

我试图在不删除任何相关信息的情况下简化这一点,所以这里......

我正在尝试重写当前聚合数据的视图,但基于某些数据的聚合,它可能包含或不包含其他数据。例如:

;WITH CTE_ExtraFees AS
(
    SELECT AccountID, SUM(Amount) AS TotalAmount
    FROM AccountFees
    WHERE
        FeeType = 'EXTRA' AND
        AccountType = 'P'
    GROUP BY
        AccountID
)
SELECT
    AccountID,
    CASE
        WHEN SUM(F.Amount) > 0 THEN SUM(F.Amount) - XF.TotalAmount
        ELSE SUM(F.Amount)
    END AS FeeAmount
FROM
    AccountFees F
LEFT OUTER JOIN CTE_ExtraFees XF ON XF.AccountID = F.AccountID
GROUP BY
    F.AccountID,
    XF.TotalAmount

除了额外的费用之外还有更多的逻辑,但我已经完成了所有这些,上面是我的最后一个关键点。我现在有类似的东西:

SELECT
    AccountID,
    SUM(Amount) AS FeeAmount
FROM
    AccountFees
WHERE
    (
        FeeType <> 'EXTRA' OR
        AccountType <> 'P'
    )
GROUP BY
    AccountID

问题当然是SUM(Fees) <= 0我最终还是排除了额外的费用。

我想避免出于性能原因而执行多个聚合,所以我希望在一个聚合中完成所有这些,但我似乎无法想出任何东西来完成相同的逻辑。

感谢您提供任何帮助或建议!

2 个答案:

答案 0 :(得分:2)

SELECT
      AccountID
    , FeeAmount =
        CASE WHEN SUM(Amount) > 0
            THEN SUM(Amount) - SUM(CASE WHEN FeeType = 'EXTRA' AND AccountType = 'P' THEN Amount ELSE 0 END)
            ELSE SUM(Amount)
        END
FROM dbo.AccountFees
GROUP BY AccountID

答案 1 :(得分:2)

怎么样

SELECT
    AccountID,
    SUM(
        CASE WHEN FeeType = 'EXTRA' AND AccountType = 'P'
            THEN -1 * Amount
            ELSE Amount
        END
    ) AS FeeAmount
FROM AccountFees
GROUP BY AccountID

我认为他们在这个问题上可能缺少的关键部分是你可以在case语句上运行Sum函数,这个函数在我的答案和Devart的答案中使用(顺便说一下,我觉得更全面地包含原始查询的逻辑)。 case语句将逐行触发,然后将其结果提供给sum函数,从而产生条件求和函数。