【问题标题】:SQL Server - logic to allow me to do a calculation in the where statementSQL Server - 允许我在 where 语句中进行计算的逻辑
【发布时间】:2024-05-21 19:00:01
【问题描述】:

我已经为我的特定问题寻找了很长时间的答案。

我被要求创建一个脚本来提取邮件合并的数据。我们的计费团队需要确定我们已向其发送最终警告通知但仍未支付账单的用户。

我无法克服的最大挑战是一些客户可能做了以下其中一项:

  1. 未支付任何未付款项
  2. 一次性付清欠款
  3. 通过多次付款全额支付了未付款项
  4. 在一次或多次付款中支付了部分未付款项

用于生成最终警告通知的数据在一个表中,未结金额显示为正数,任何已支付的款项在不同的表中显示为负数。

在我的查询中,从场景 1 和 2 中识别客户将相当容易识别,但 3 和 4 让我很头疼。我的想法是将未付金额添加到任何付款的总和中。如果总和 > 0,则客户没有支付足够的金额来支付未偿金额。我开发了一个子查询来获取某个日期之后的所有付款总额,但我无法获得将其添加到未结金额然后检查余额是否大于 0 的查询。我得到错误是“无法对包含聚合或子查询的表达式执行聚合函数。”

有人可以推荐一种不同的查询方法吗?

SELECT 
    finalwarning.table_no AS [Property No], 
    finalwarning.value_1 AS [Arrears Balance], 
    finalwarning.date_1 AS [Notice Date] 
FROM 
    finalwarning  
WHERE
    finalwarning.table_no = 172030 
    AND finalwarning.ref_3 = 'Final' 
    AND ((SELECT 
              CASE
                 WHEN EXISTS (SELECT 1 
                              FROM paymentsmade 
                              WHERE PROPERTY_NO = 1234 
                                AND TRANSACTION_DESC = 'Receipt' 
                                AND TRANSACTION_DATE > '2017-05-01 00:00:00.000' 
                             GROUP BY TRANSACTION_DESC) 
                   THEN (SELECT SUM(amount) 
                         FROM paymentsmade 
                         WHERE paymentsmade.PROPERTY_NO = 1234 
                           AND paymentsmade.TRANSACTION_DESC = 'Receipt' 
                           AND paymentsmade.TRANSACTION_DATE > '2017-05-01 00:00:00.000' 
                         GROUP BY paymentsmade.TRANSACTION_DESC)    
                   ELSE '0' 
              END) + finalwarning.value_1) < 0

【问题讨论】:

    标签: sql sql-server-2008-r2


    【解决方案1】:

    CTE 是我们的朋友,他们确实帮助我们完成了艰苦的工作,并允许更轻松地编写核心 SQL。下面的示例采用您的结构并应用付款 CTE 的概念,它将按财产编号汇总付款,并提供您在评估中需要执行的所有计算。我不确定日期是如何起作用的,并且连接可能是错误的,因为在示例中为 property_no 提供了 2 个不同的数字,但我认为它们是相同的。

    WITH paymentCTE  (property_no, amount, transaction_desc, cntpayments) 
    as
    (select property_no, sum(amount) as amount, transaction_desc, count(*) 
    from paymentsmade
    where TRANSACTION_DATE > > '2017-05-01 00:00:00.000' 
    group by property_no, transaction_desc
    )
    
    SELECT fw.table_no AS [Property No]
    , fw.value_1 AS [Arrears Balance]
    , fw.date_1 AS [Notice Date]
    , coalesce(p1.amount,0) as [Payments Made]
    , fw.value_1+coalesce(p1.amount,0) as [Outstanding Balance]
    , coalesce(p1.cntpayments, 0) as [Number of Payments]
    FROM finalwarning fw 
    left outer join paymentCTE p1 
    on fw.table_no = p1.property_no 
    and p1.Transaction_desc = 'Receipt'
    WHERE p1.cntpayments is null
    or (coalesce(p1.cntpayments, 0) = 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
    or (coalesce(p1.cntpayments, 0) > 1 and fw.value_1 + coalesce(p1.amount,0) = 0)
    or (coalesce(p1.cntpayments, 0) > 0 and fw.value_1 + coalesce(p1.amount,0)<> 0)
    

    【讨论】:

    • 您应该努力与您编写 SQL 关键字的方式一致 - 要么 以全部大写形式(SELECT、FROM)编写它们,或全部小写(select、from)或混合大小写(Select、From) - 但请选择一种样式,然后坚持使用它 - 不要将它们混合在一起!
    • 感谢 Louise,我以前从未使用过 CTE,但我认为现在它也是我的朋友 :)
    最近更新 更多