当前位置: 代码迷 >> Oracle认证考试 >> 数据统计偏题
  详细解决方案

数据统计偏题

热度:132   发布时间:2016-04-24 03:48:15.0
数据统计难题
已有充值表和消费表,要求统计每个月的卡充值总额和这些卡至今的消费总额。举例如下:
充值表(CZ):
卡号(cardno) 充值次数(times) 充值日期(loddate) 充值金额(lodamt)
91034567 1 2010-2-12 100
91034567 2 2010-5-21 100
91034567 3 2010-9-16 200
91045678 1 2010-3-1 200
91045678 2 2010-3-23 300
91056789 1 2010-2-19 300
。。。。。。
消费表(XF):
卡号(cardno) 面值(blance) 消费金额(amt) 消费日期(date) 
91034567 100 40.00 2010-2-15 
91034567 100 60.00 2010-3-26 
91034567 100 100.00 2010-8-11
91034567 100 160.00 2010-10-3  
91045678 200 120.00 2010-3-1 
91045678 200 80.00 2010-3-5 
91045678 200 220.00 2010-5-15 
91056789 300 278.00 2010-5-2 
。。。。。。。
统计2月份的数据如下:
充值总额(lodall)= 400(100+300 )
消费总额(amtall)= 378(40+60+278)
统计3月份数据
充值总额(lodall)= 500(200+300 )
消费总额(amtall)= 200(120+80)
。。。。。。。
要求格式如下:
LODDATE     LODALL        AMTALL
-------   ----------   ----------
201002         400        378
201003         500        200
。。。。。。
统计每个月的充值总额没有问题,但统计每个月的消费总额就比较困难了。因为卡片可以回收,所以存在一个卡号重复使用(如91034567,第一次2月份充值后全部消费完,第二次5月份充值又使用了),请各位大侠帮助一下,怎么写这个统计语句?

注意三点:
1、不是月度统计,是统计卡片从充值到当前为止的消费,但要考虑回收问题,如果回收后再次充值,则此后的消费计算在下次充值后的消费统计中
2、同一张卡片前后几次充值的金额可以不同
3、卡片的面额等于第一次的充值金额,以后再充值,面额不会变
------解决方案--------------------
SQL> SELECT * FROM cz;
 
CARDNO        TIMES LODDATE         LODAMT
-------- ---------- ----------- ----------
91034567          1 2010-2-12          100
91034567          2 2010-5-21          100
91034567          3 2010-9-16          200
91045678          1 2010-3-1           200
91045678          2 2010-3-23          300
91056789          1 2010-2-19          300
 
6 rows selected
SQL> SELECT * FROM xf;
 
CARDNO       BLANCE        AMT PAYDATE
-------- ---------- ---------- -----------
91034567        100         40 2010-2-15
91034567        100         60 2010-3-26
91034567        100        100 2010-8-11
91034567        100        160 2010-10-3
91045678        200        120 2010-3-1
91045678        200         80 2010-3-5
91045678        200        220 2010-5-15
91056789        300        278 2010-5-2
 
8 rows selected
SQL> SELECT to_char(loddate, 'yyyymm') loddate, SUM(lodamt) lodall, SUM(amt) amtall
  2    FROM (SELECT c.*,
  3                 (SELECT SUM(amt)
  4                    FROM xf x
  5                   WHERE c.cardno = x.cardno
  6                     AND x.paydate BETWEEN c.loddate AND c.lloddate) amt
  7            FROM (SELECT cz.*,
  8                         lead(loddate, 1, DATE '3000-01-01')
  9                         over (PARTITION BY cardno ORDER BY loddate) - 1 lloddate
 10                    FROM cz) c)
 11   GROUP BY to_char(loddate, 'yyyymm');
  相关解决方案