【问题标题】:Obtaining payment dates of debit using credit payment dates and aggregates in SQL - slow query在 SQL 中使用贷方付款日期和聚合获取借方的付款日期 - 慢查询
【发布时间】:2019-08-25 20:56:41
【问题描述】:

Edit2: CTE 是查询缓慢的原因。问题解决了。

编辑:我将创建另一列付款日期,而不是更新。以下代码完美运行,但速度非常慢。有没有其他方法可以更快地做到这一点?

WITH sum_data AS (SELECT CustomerID
                   , ISSUEDATE
                   , DEBIT
                   , CREDIT
                   , SUM(DEBIT) over(PARTITION BY CustomerID 
                                     ORDER BY ISSUEDATE
                                     ROWS UNBOUNDED PRECEDING) SUM_DEBIT
                   , SUM(CREDIT) over(PARTITION BY CustomerID
                                      ORDER BY ISSUEDATE
                                      ROWS UNBOUNDED PRECEDING) SUM_CREDIT
               FROM Test_Table)
SELECT d.CustomerID
 , d.ISSUEDATE
 , d.DEBIT
 , d.CREDIT
 , (SELECT MIN(ISSUEDATE) 
               FROM sum_data d2
               WHERE d2.SUM_CREDIT >= d.SUM_DEBIT
                 AND d2.CustomerID  = d.CustomerID) PAYMENTDATE
FROM sum_data d
WHERE DEBIT != 0 

预编辑:我有一个显示不同客户交易信息的数据集。信用额度的签发日期和付款日期相同,因为它们是同时签发和支付的。但是,对于借项行,付款日期将是该借项被贷方清算的时间。所以从底部开始,我们在输入贷方之前有 4 个借方。 1398.83 贷方清除了 1336.13 借方的金额,所以我想用 2018 年 9 月 20 日的付款日期更新最后一行。它上面的 2672 信用涵盖了 1398.83 的倒数第二行,因此该行的付款日期应为 2018 年 9 月 22 日。 (1398.83-1336.13) + (2672 - 1398.83) 的剩余余额不包括剩余的借方,因此我们将继续检查新的贷方行是否涵盖借方金额,并将从最后一个条目开始清算借方(如更新付款日期)当借方被清算时,我们将使用清算贷方行的付款日期更新付款日期,如上例所示。这将针对所有不同的客户 ID(分区依据)完成。

CustomerID  ISSUEDATE   DEBIT   CREDIT  
M00008      4/2/2019    1345.53 0       
M00008      3/19/2019   0       1336.13 
M00008      3/18/2019   0       1403.4  
M00008      3/4/2019    1406.13 0       
M00008      3/4/2019    1336.13 0       
M00008      2/28/2019   0       1336.13 
M00008      2/21/2019   0       1399.19 
M00008      2/4/2019    1403.4  0       
M00008      2/4/2019    1336.13 0       
M00008      1/28/2019   0       1513    
M00008      1/22/2019   0       1337.94 
M00008      1/4/2019    1398.83 0       
M00008      1/4/2019    1336.13 0       
M00008      12/3/2018   1513.03 0       
M00008      12/3/2018   1336.13 0       
M00008      11/19/2018  0       2958    
M00008      11/19/2018  0       2908.25 
M00008      11/5/2018   1461.56 0       
M00008      11/2/2018   1367.92 0       
M00008      10/20/2018  0       1336.13 
M00008      10/19/2018  0       1398.83 
M00008      10/3/2018   1489.94 0       
M00008      10/2/2018   1541.03 0       
M00008      9/22/2018   0       2672    
M00008      9/20/2018   0       1398.83 
M00008      9/3/2018    1398.83 0       
M00008      9/3/2018    1336.13 0       
M00008      8/3/2018    1398.83 0       
M00008      8/2/2018    1336.13 0       

上述数据集查询的输出:

CustomerID  ISSUEDATE   DEBIT    CREDIT PAYMENTDATE
M00008      2018-08-02  1336.13  0.00   2018-09-20
M00008      2018-08-03  1398.83  0.00   2018-09-22
M00008      2018-09-03  1398.83  0.00   2018-10-19
M00008      2018-09-03  1336.13  0.00   2018-10-20
M00008      2018-10-02  1541.03  0.00   2018-11-19
M00008      2018-10-03  1489.94  0.00   2018-11-19
M00008      2018-11-02  1367.92  0.00   2018-11-19
M00008      2018-11-05  1461.56  0.00   2018-11-19
M00008      2018-12-03  1513.03  0.00   2019-01-22
M00008      2018-12-03  1336.13  0.00   2019-01-28
M00008      2019-01-04  1398.83  0.00   2019-02-21
M00008      2019-01-04  1336.13  0.00   2019-02-21
M00008      2019-02-04  1403.40  0.00   2019-03-18
M00008      2019-02-04  1336.13  0.00   2019-03-18
M00008      2019-03-04  1406.13  0.00   NULL
M00008      2019-03-04  1336.13  0.00   NULL
M00008      2019-04-02  1345.53  0.00   NULL

【问题讨论】:

  • 这是可能的,但我认为这是人们每年获得 20 万美元以上的报酬来解决的问题。您是否有自己编写的某种查询来解决需要帮助的问题?我想这可能需要专业人员一天的时间来编写并确保它是防弹的,因此期望有人为您编写整个查询以获得 +25 的声誉有点不合理。
  • 我添加了我使用的代码并稍微更改了措辞。我没有更新,而是创建了另一个名为“付款日期”的列,并且我在上面添加的代码完美运行。不过需要很长时间。我想知道是否有另一种方法可以更快地做到这一点。

标签: sql tsql sql-server-2012


【解决方案1】:

在 select 语句中使用 select 总是会影响性能。对于您的查询,使用 CROSS APPLY 应该更快地产生结果。

WITH sum_data AS (SELECT CustomerID
               , ISSUEDATE
               , DEBIT
               , CREDIT
               , SUM(DEBIT) over(PARTITION BY CustomerID 
                                 ORDER BY ISSUEDATE
                                 ROWS UNBOUNDED PRECEDING) SUM_DEBIT
               , SUM(CREDIT) over(PARTITION BY CustomerID
                                  ORDER BY ISSUEDATE
                                  ROWS UNBOUNDED PRECEDING) SUM_CREDIT
           FROM Test_Table)
 SELECT d.CustomerID
      , d.ISSUEDATE
      , d.DEBIT
      , d.CREDIT
      , PaymentDate
   FROM sum_data d
   CROSS APPLY (SELECT MIN(ISSUEDATE) AS PaymentDate
           FROM sum_data d2
           WHERE d2.SUM_CREDIT >= d.SUM_DEBIT
             AND d2.CustomerID  = d.CustomerID) t
   WHERE DEBIT != 0 

【讨论】:

  • 请注意,cross apply 的工作方式与 inner join 类似,在 apply 中没有匹配记录的情况下,不会返回任何内容。如果您需要left join 类型的行为,您可以使用outer apply
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2016-09-04
  • 2013-12-18
  • 1970-01-01
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多