Sql 找到满足两种不同聚合标准的记录的更好方法?
我需要找到信贷交易总额大于或等于阈值金额,而借方交易总额小于或等于相同阈值金额的倒数的客户。我还想返回总交易金额满足信用和借记阈值的交易。我提出了两个解决方案,但我认为我可能会使事情变得比必要的更复杂 下面是一些简化的示例数据Sql 找到满足两种不同聚合标准的记录的更好方法?,sql,sql-server,sum,aggregate-functions,sql-server-2016,Sql,Sql Server,Sum,Aggregate Functions,Sql Server 2016,我需要找到信贷交易总额大于或等于阈值金额,而借方交易总额小于或等于相同阈值金额的倒数的客户。我还想返回总交易金额满足信用和借记阈值的交易。我提出了两个解决方案,但我认为我可能会使事情变得比必要的更复杂 下面是一些简化的示例数据 TransactionID CustomerID TransactionDate TransactionType TransactionAmount ------------- ---------- --------------- -------------
TransactionID CustomerID TransactionDate TransactionType TransactionAmount
------------- ---------- --------------- --------------- -----------------
1 1 2020-10-01 Credit 10.25
2 1 2020-10-02 Credit 11.50
3 1 2020-10-02 Debit -13.25
4 2 2020-10-01 Credit 14.22
5 2 2020-10-02 Debit -50.75
6 2 2020-10-04 Credit 12.85
7 2 2020-10-07 Debit -4.53
8 3 2020-10-02 Credit 12.85
CustomerID 2的阈值金额为20美元,是唯一一个信用和借记都达到该阈值的客户。这是我的预期结果
TransactionID CustomerID TransactionDate TransactionType TransactionAmount
------------- ---------- --------------- --------------- -----------------
4 2 2020-10-01 Credit 14.22
6 2 2020-10-04 Credit 12.85
5 2 2020-10-02 Debit -50.75
7 2 2020-10-07 Debit -4.53
我提出了两个解决办法。我应该提到,由于我最终需要嵌入这个查询的软件,我不能使用临时表或表变量
解决方案1
下面是我的示例数据插入和两个解决方案的示例。如果我不能使用临时表或表变量,有没有更好的方法来执行此操作?您可以使用窗口函数:
select transactionid, customerid, transactiondate, transactiontype, transactionamount
from (
select t.*,
sum(case when transactiontype = 'Credit' then transactionamount else 0 end)
over(partition by customerid) sum_credit,
sum(case when transactiontype = 'Debit' then transactionamount else 0 end)
over(partition by customerid) sum_debit
from transactions t
) t
where sum_credit > @ThresholdAmount and sum_debit < - @ThresholdAmount
order by customerid, transactiontype, transactiondate
在子查询中,条件和计算每个客户的借方和贷方总额。然后,您可以使用此信息在外部查询中进行筛选。也许您所追求的是HAVING中的某个条件聚合?尽管这不会返回任何行,因为没有客户的信贷交易总额大于阈值金额,而借方交易总额大于相同的阈值金额。这是因为所有借记交易都有负值,负值之和永远不能为正值,因此永远不能大于示例中的值20: 声明@ThresholdAmount NUMERIC10,2; 设置@ThresholdAmount=20.00; 选择CustomerID 来自dbo.Transactions 按客户ID分组 当'Credit'然后TransactionMount END>@ThresholdAmount时具有SUMCASE TransactionType 当'Debit'然后TransactionMount END>@ThresholdAmount时的SUMCASE TransactionType和SUMCASE TransactionType;
我需要澄清这个要求。给定20美元的阈值金额,我正在寻找信用交易总额大于或等于该阈值金额,而借记交易总额小于或等于该阈值金额的倒数的客户。因此,如果客户在借记交易中有-30美元,我会说他们达到了阈值。如果我将HAVING子句的最后一部分更改为<@ThresholdAmount*-1,则我将获得客户ID 2。我为不准确的要求道歉。我是用商业术语而不是技术术语来思考的。
WITH txn_cte (TransactionID, CustomerID, TransactionDate, TransactionType, TransactionAmount, TransactionAmountTotal) AS
(
SELECT
txn.TransactionID
, txn.CustomerID
, txn.TransactionDate
, txn.TransactionType
, txn.TransactionAmount
, txn.TransactionAmountTotal
FROM (
SELECT
TransactionID
, CustomerID
, TransactionDate
, TransactionType
, TransactionAmount
, SUM(TransactionAmount) OVER (PARTITION BY CustomerID, TransactionType) AS [TransactionAmountTotal]
FROM Transactions
) txn
WHERE ABS(txn.TransactionAmountTotal) >= @ThresholdAmount
)
SELECT
txn_cte.TransactionID
, txn_cte.CustomerID
, txn_cte.TransactionDate
, txn_cte.TransactionType
, txn_cte.TransactionAmount
FROM txn_cte
WHERE EXISTS (
SELECT txn_cte1.TransactionID
FROM txn_cte txn_cte1
WHERE txn_cte1.TransactionType = 'Credit'
AND txn_cte1.CustomerID = txn_cte.CustomerID
)
AND EXISTS (
SELECT txn_cte2.TransactionID
FROM txn_cte txn_cte2
WHERE txn_cte2.TransactionType = 'Debit'
AND txn_cte2.CustomerID = txn_cte.CustomerID
)
ORDER BY txn_cte.CustomerID
, txn_cte.TransactionType
, txn_cte.TransactionDate;
select transactionid, customerid, transactiondate, transactiontype, transactionamount
from (
select t.*,
sum(case when transactiontype = 'Credit' then transactionamount else 0 end)
over(partition by customerid) sum_credit,
sum(case when transactiontype = 'Debit' then transactionamount else 0 end)
over(partition by customerid) sum_debit
from transactions t
) t
where sum_credit > @ThresholdAmount and sum_debit < - @ThresholdAmount
order by customerid, transactiontype, transactiondate