oracle开发 奇葩的需求--连续数据分组

昨天业务提了个需求,一下子把我给难住了,想了两小时没想出来(为毛奇葩的需求老是提到俺们这边,俺真心不是万能的啊),只好求助万能的itpub,大牛给了些不错的思路。现总结如下
需求简化后的版本如下
有这么一张表如下:
订单号    商品号    付款时间  用户
   1           A              11.27    甲
   1           B              11.27    甲
   2           B              12.2      乙
   3           C              12.3      甲

订单商品表,订单号一样的,付款时间、用户也保证一样。
现在要求找出那些在一个月内(30天)买过三种不同商品的客户。一个月是指连续的一个月,不是指自然月。
比如这个例子中,甲27号买了2个商品,3号又买了1个商品,所以他在连续一个月内买了三个不同的商品,需要把他取出来。

这个需求的难点在于时间要求连续而非自然月,意味着不能按月进行group by。

不罗嗦了,先建测试表
create table temp
(
  order_id number,
  goods_id varchar2(100),
  pay_time date,
  user_id  varchar2(100)
);
insert into temp values(1,'A',date'2013-11-27','甲');
insert into temp values(1,'B',date'2013-11-27','甲');
insert into temp values(2,'B',date'2013-12-2','乙');
insert into temp values(3,'C',date'2013-12-3','甲');

最先想到的思路是取一天,然后查看它后面30天的商品购买情况,不断循环往后取,直到满足条件或者数据取完。这个貌似不能用一句sql就能解决了,所以就写了个存储过程,按本示例改写后如下:
create or replace procedure zybiro.p_temp
is
  start_date date;
  end_date   date;
  v_user_id  varchar2(100);
begin
  select trunc(min(pay_time)),trunc(max(pay_time)) into start_date,end_date from temp;
  
  loop
    exit when start_date>=end_date;
  begin
  select user_id into v_user_id from temp where trunc(pay_time)<=start_date+30 and trunc(pay_time)>=start_date
     group by user_id having count(distinct goods_id)>=3;
  exception 
    when others then
      v_user_id:='null';
   end;
   if v_user_id <> 'null' then
      dbms_output.put_line('user_id is : '||v_user_id);
   end if;
    start_date:=start_date+1;
  end loop;
  commit;
end;


这里为方便起见用v_user_id变量直接输出。实际环境是不能这么搞的,因为主语句一次输出可能不止一个。正确的搞法是创建张临时表把数据都导进去。

不管怎么说,证明这种方式是可行的。记得先运行set serveroutput on;
oracle开发 奇葩的需求--连续数据分组 - scjthree - 亚存的博客

PUB上有类似的一道题目

用了一堆分析函数解决。貌似我自己还没研究透,有时间再看看补充进去



 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值