如何验证是否有12个连续付款

时间:2010-10-05 19:01:33

标签: sql database oracle database-design optimization

例如:

我有这种情况,我们收到付款,每个家庭单独付款,并使用DB中的金额注册这些付款。

问题是家庭可以将贷款从bank1转移到bank2,只要他们有12次或更多次连续付款。

例如,如果他们已经注册了

的付款
oct, nov, dec, jan, feb, mar, apr, may, jun, jul, ago, and sept.

feb未收到任何付款,计数将从march重新开始。

同事建议最好的方法是,在每次付款注册中计算总付款数,并在名为int的{​​{1}}列中注册总顺序付款。

为:

sequential

我认为,必须有一种方法,Payment Family Bank Date Sequential --------------------------------------------------------- 1200 2 1 10-22-2009 1 1200 2 1 11-22-2009 2 . . . 1200 2 1 08-22-2010 11 1200 2 1 09-22-2010 12 列是不必要的,如果我想验证最后sequential 12行是否连续只有order by Date DESC个月差。

任何想法?

编辑:

  • 1中将有数百万rows

  • 还希望只有表格中的日期并在table

  • 处理它们

5 个答案:

答案 0 :(得分:5)

<强>分析!

数据:

create table payments
(amount       number,
 family       number,
 bank         number,
 payment_date date
);

insert into payments values (1200, 2, 1, date '2010-01-01');
insert into payments values (1200, 2, 1, date '2010-02-02');
insert into payments values (1200, 2, 1, date '2010-03-03');
insert into payments values (1200, 2, 1, date '2010-04-04');
insert into payments values (1200, 2, 1, date '2010-05-05');
insert into payments values (1200, 2, 1, date '2010-06-07');
insert into payments values (1200, 2, 1, date '2010-07-07');
--skip august
--insert into payments values (1200, 2, 1, date '2010-08-08');
insert into payments values (1200, 2, 1, date '2010-09-09');
insert into payments values (1200, 2, 1, date '2010-10-10');
insert into payments values (1200, 2, 1, date '2010-11-11');
--double pay november
insert into payments values (1200, 2, 1, date '2010-11-30');
insert into payments values (1200, 2, 1, date '2010-12-12');

查询:

select * 
  from (select family, bank, 
               trunc(payment_date, 'mon') as payment_month,
               lead ( trunc(payment_date, 'mon')) 
                 over ( partition by family
                        order by payment_date) 
                 as next_payment_month
          from payments 
         order by payment_date desc 
       )
       -- eliminate multiple payments in month
 where payment_month <> next_payment_month
       -- find a gap
   and add_months(payment_month, 1) <> (next_payment_month)
       -- stop at the first gap
   and rownum = 1

结果:

    FAMILY       BANK PAYMENT_M NEXT_PAYM
---------- ---------- --------- ---------
         2          1 01-JUL-10 01-SEP-10

您可以使用NEXT_PAYMENT_MONTH中的值来执行应用程序级别所需的任何比较。


SELECT trunc(MONTHS_BETWEEN(SYSDATE, DATE '2010-01-01')) FROM DUAL

给你几个月 - 这就是我在应用程序级别使用值的意思。

所以这个:

select trunc(
       months_between(sysdate, 
         (select next_payment_date
            from (select family, bank, 
                         trunc(payment_date, 'mon') as payment_month,
                    lead ( trunc(payment_date, 'mon')) 
                    over ( partition by family
                           order by payment_date) 
                      as next_payment_month
                    from payments 
                   where family = :family
                   order by payment_date desc 
                 )
           where payment_month <> next_payment_month
             and add_months(payment_month, 1) <> (next_payment_month)
             and rownum = 1
          ) 
       )
  from dual

自上次错过的月份以来连续付款给你几个月。

答案 1 :(得分:1)

要验证单个家庭在过去12个月内是否有12个连续付款,无论银行如何,请使用:

select sum(payment)                          total_paid, 
       count(*)                              total_payments, 
       count(distinct trunc(pay_date,'mon')) paid_months
from   payment_table
where  family = :family and pay_date between :start_date and :end_date;

total_payments表示该期间内的付款次数,而paid_months表示付款的单独月份数。

如果要检查他们是否已在所选时间段内切换银行,请在上述查询中添加group by bank子句。

要列出在此期间内有12个不同月份付款的所有家庭,请使用:

select family,
       sum(payment)                          total_paid, 
       count(*)                              total_payments, 
       count(distinct trunc(pay_date,'mon')) paid_months
from   payment_table
where  pay_date between :start_date and :end_date
group by family
having count(distinct trunc(pay_date,'mon')) = 12;

如果要将结果限制为在所选时间段内尚未切换银行的家庭,请在上述查询的and count(distinct bank) = 1子句中添加having条件。

我建议确保付款表上有关于family和pay_date的索引。

答案 2 :(得分:0)

我认为简单的查询会有所帮助,请查看:

SELECT COUNT(*)
FROM payments p
WHERE p.Family = 2 AND p.Date between '01-01-2009' and '12-01-2009'
通过这种方式,您可以获得当前表结构的任何日期之间的付款数量。

答案 3 :(得分:0)

这个怎么样:

SELECT  PT.Payment
      , PT.Family
      , PT.Bank
      , PT.Date
      , (SELECT COUNT(*) FROM PaymentTable T
         WHERE DATEDIFF (d, T.Date, PT.Date) < 31) as IsSequential
  FROM PaymentsTable PT

上述查询会告诉您每笔付款是否为连续付款(即如果付款的前一个月):

然后,您可以运行查询以确定是否针对特定月份或特定家庭进行了12次连续付款。

假设您要显示至少有12个连续付款的所有家庭:

SELECT  ST.Family
     , COUNT(ST.IsSequential) as NumberOfSequentialPayments
 FROM
  (SELECT   PT.Payment
          , PT.Family
          , PT.Bank
          , PT.Date
          , (SELECT COUNT(*) FROM PaymentTable T
          WHERE DATEDIFF (d, T.Date, PT.Date) < 31) as IsSequential
     FROM PaymentsTable PT
   ) AS ST
  WHERE NumberOfSequentialPayments >= 12
 GROUP BY ST.Family

答案 4 :(得分:0)

可以像其他人指出的那样去做。

但是,当你有关系数据时,情况就不是这样了,但你按顺序做事,这是坏事

这是业务规则本质上是顺序的情况;在这种情况下,具有顺序辅助字段可能

  • 简化您的查询
  • 提高性能(如果你谈论100M记录,这个sudenlly几乎成为最高评级因素,并且会出现各种非规范化的想法)
  • 了解其他业务规则(允许更多功能和灵活性)

最后一点:我认为最完整的解决方案需要重新检查业务规则 - 您可能会发现用户会谈论'错过付款',这表示其他表格,例如“付款计划/时间表”和与其他流程相关联,这可能是错过付款列或顺序值的正确位置......此结构还将支持宽限期,预付款等方面的灵活性......