【问题标题】:Calculate payment date for each invoice计算每张发票的付款日期
【发布时间】:2017-11-26 11:51:07
【问题描述】:

请考虑下表transaction:一家公司定期向其客户发送属于同一订单的发票。这些公司的客户通常每这么多周只支付一次。

trans_date 格式为 yyyy-mm-dd

id    order_id    trans_type    trans_date    trans_amount
----------------------------------------------------------
1        1          invoice     2017-01-10        100
2        1          invoice     2017-05-23        150
3        1          invoice     2017-05-28        200
4        2          invoice     2017-03-01        700
5        2          payment     2017-06-16        700
6        1          payment     2017-10-12        450
7        3          invoice     2017-06-24        199

公司希望了解每张发票的付款日期。例如:发票 (id) 1(order_id=1 组的一部分)在2017-01-10 上发送并在2017-10-12id=6))上付款。id=7 的发票根本没有付款。

所需的输出是每张发票的付款日期 (payment_date):

id    order_id    trans_type    trans_date    trans_amount    payment_date
--------------------------------------------------------------------------
1        1          invoice     2017-01-10        100         2017-10-12
2        1          invoice     2017-05-23        150         2017-10-12
3        1          invoice     2017-05-28        200         2017-10-12
4        2          invoice     2017-03-01        700         2017-06-16
5        2          payment     2017-06-16        700
6        1          payment     2017-10-12        450
7        3          invoice     2017-06-24        199

对于交易 5、6 和 7,payment_date 为空,因为它要么是付款(id=56),要么是未付发票(id=7)。

我不明白我应该如何解决这个问题。结合常规脚本,我会得到整个集合并循环通过它来查找每笔付款。但是如何仅在 SQL 中解决呢?

任何帮助将不胜感激!

【问题讨论】:

  • 是否有可能只支付部分金额?在您的示例中,付款 id (6) 将是 357 ?如果不是并排除其他一些边缘情况,我认为这是可能的
  • @a_horse_with_no_name 我添加了一些标签。我正在使用 SQL Server 2012。感谢您的建议!
  • @Mzf 理论上确实有可能付款只是金额的一部分,但这些都是例外。很好的收获,但我不明白这是怎么解释的,所以我把它排除在外。目前,我假设所有付款都将全额支付。

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


【解决方案1】:

您尝试过简单的左连接吗? 下面的代码是标准 SQL。

Select a.id ,   a.order_id,    a.trans_type,    a.trans_date,    a.trans_amount,    isnull(b.trans_date, '')  As payment_date
From transaction a
Left join transaction b
On a.order_id = b.order_id
And a.trans_type = 'invoice' 
And b.trans_type = 'payment'

【讨论】:

  • 如果我这样做,输出中的行数会增加。实际上,我在表 transactions 中有 50'000 行,但是当将表连接到自身时,输出约为 70'000 行。什么是可能的解释?
  • 我能想到的唯一可能的情况是,一个order_id 有多个payment 行。
【解决方案2】:

您可以对付款和发票进行累计,并获得付款总额达到或超过发票总额的第一个日期:

with ip as (
      select ip.*,
             sum(case when ip.trans_type = 'invoice' then ip.trans_amount else 0 end) over (order by ip.trans_date) as running_invoice,
             sum(case when ip.trans_type = 'payment' then ip.trans_amount else 0 end) over (order by ip.trans_date) as running_payment,
      from invoicepayments i
     )
select ip.*,
       (select min(ip2.trans_date)
        from ip ip2
        where ip2.running_payment >= ip.running_invoice and
              ip.trans_type = 'invoice'
       ) as payment_date
from ip;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-10
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多