SQL解决过去M天内连续N天符合某条件问题
本博客是来源CSDN BBS上一个问题。原问题如下:
从系统时间往前M天内,有连续M天交易笔数小于B笔的商户。
表设计:
CREATE TABLE prm_tbl(zoneno NUMBER, last_days NUMBER, min_days NUMBER, min_trans NUMBER);
CREATE TABLE acc_tbl(d_date DATE, merch NUMBER, cnt NUMBER);
CREATE TABLE merch_list(merch NUMBER, zoneno NUMBER);
prm_tbl定义某问题描述中的三个参数。
acc_tbl是交易记录表,假如商户在某天没有交易,则该表没有数据。
merch_list是商户和区域的关联表。某区域内有一个或多个商户。
测试数据如下:
$sh@ORCL> select * from prm_tbl;ZONENO LAST_DAYS MIN_DAYS MIN_TRANS
------ --------- -------- ---------1 5 2 62 5 3 6Elapsed: 00:00:00.05
$sh@ORCL> select * from acc_tbl order by d_date desc;D_DATE MERCH CNT
--------- ---------- ----------
03-JAN-14 1 7
02-JAN-14 1 6
01-JAN-14 1 7
31-DEC-13 1 4
30-DEC-13 1 7
29-DEC-13 1 3Elapsed: 00:00:00.01
$sh@ORCL> select * from merch_list;MERCH ZONENO
----- ------1 12 2
可以看出merch = 1是不符合条件的,他小于B笔交易的天数不连续。而merch = 2在这段时间没有交易,显然是符合条件的。
用Java, PL/SQL等procedual based语言通过循环可以解决该问题,但这里只讨论基于集合的SQL来解决问题。在数据库中,通常基于集合的运算比“基于过程”的效率高!
需要解决的几个问题:
1. 交易在时间和区域两个维度上是稀疏的,即商户可能在某个区域某段时间没有交易。这是一个双维度的“数据稠化”问题。
2. 连续N天如何解决?
问题1的解决办法在我另一个博客中已有介绍 http://blog.csdn.net/chncaesar/article/details/17321267,这里的问题更复杂,请看SQL:
with all_data as(
select ml.zoneno, ml.merch, date_id, nvl(tran_cnt,0) tran_cnt, row_number() over(partition by ml.zoneno, ml.merch order by date_id desc) rn from
(select acc.merch, dates.date_id, nvl(acc.cnt,0) tran_cnt from acc_tbl acc partition by (merch) right outer join (select trunc(sysdate) - level date_id from dual connect by level <= (select max(last_days) from prm_tbl)) dates
on acc.d_date=dates.date_id) merch_dates partition by (merch, date_id) right outer join merch_list ml on merch_dates.merch=ml.merch
)
select * from all_data;
但是问题1还没有完全解决,每个区域的过去M天,M取值是不一样的,我们还需要一个连接来完成这事。
with all_data as(
select ml.zoneno, ml.merch, date_id, nvl(tran_cnt,0) tran_cnt, row_number() over(partition by ml.zoneno, ml.merch order by date_id desc) rn from
(select acc.merch, dates.date_id, nvl(acc.cnt,0) tran_cnt from acc_tbl acc partition by (merch) right outer join (select trunc(sysdate) - level date_id from dual connect by level <= (select max(last_days) from prm_tbl)) dates
on acc.d_date=dates.date_id) merch_dates partition by (merch, date_id) right outer join merch_list ml on merch_dates.merch=ml.merch
),
filtered_data as(
select ad.*, pt.min_days,pt.min_trans
from all_data ad, prm_tbl pt
where ad.zoneno=pt.zoneno
and ad.rn <= pt.last_days
)
select * from filtered_data
order by zoneno, merch, date_id desc;
问题1解决。这里再给出通过笛卡尔积来实现“数据稠化”的SQL:
SELECT pt.zoneno, ml.merch, date_id, pt.last_days,pt.min_days, pt.min_transfrom prm_tbl pt, merch_list ml,(SELECT zones.zoneno, dates.date_id, row_number() over(partition by zones.zoneno order by dates.date_id desc) rn FROM(SELECT DISTINCT zoneno FROM prm_tbl) zones,(SELECT trunc(SYSDATE) - LEVEL date_id FROM dual CONNECT BY LEVEL <= (SELECT MAX(last_days) FROM prm_tbl)) dates) zone_date_vWHERE zone_date_v.zoneno=pt.zonenoAND zone_date_v.rn <= pt.last_daysAND pt.zoneno=ml.zoneno;
下面考虑问题2,现在的结果集已经包含过去M天的所有数据,连续N天的问题。请看如下SQL:
sum((case when tran_cnt <= min_trans then 1 else 0 end)) over(partition by zoneno, merch) sum_ind
计算各区域每个商户交易量少于B的天数。连续性的解决请看如下SQL:
with all_data as(
select ml.zoneno, ml.merch, date_id, nvl(tran_cnt,0) tran_cnt, row_number() over(partition by ml.zoneno, ml.merch order by date_id desc) rn from
(select acc.merch, dates.date_id, nvl(acc.cnt,0) tran_cnt from acc_tbl acc partition by (merch) right outer join (select trunc(sysdate) - level date_id from dual connect by level <= (select max(last_days) from prm_tbl)) dates
on acc.d_date=dates.date_id) merch_dates partition by (merch, date_id) right outer join merch_list ml on merch_dates.merch=ml.merch
),
filtered_data as(
select ad.*, pt.min_days,pt.min_trans,
(case when ad.tran_cnt <= pt.min_trans then 1 else 0 end) ind,
sum((case when ad.tran_cnt <= pt.min_trans then 1 else 0 end)) over(partition by ad.zoneno, ad.merch) sum_ind
from all_data ad, prm_tbl pt
where ad.zoneno=pt.zoneno
and ad.rn <= pt.last_days
),
--select * from filtered_data;
sparse_data as(
select zoneno, merch,rn, nvl(lag(rn, 1) over(partition by zoneno, merch order by date_id desc),0) pre_rn
from filtered_data
where ind=1
and sum_ind >= min_days
)
select distinct zoneno, merch from sparse_data
where rn - pre_rn =1;ZONENO MERCH
---------- ----------2 2
在这里,rn - pre_rn=1即表示是连续的。
SQL解决过去M天内连续N天符合某条件问题相关推荐
- SQL实战篇:SQL解决连续X天的问题
上一节内容,通过用户留存率的案例,讲解了解决近X天问题的思路,接下来,在本节内容来看看关于连续X天的问题,该类问题是面试和实际业务中经常需要解决的问题. 首先对连续指标.做个定义,如下: 1日连续:当 ...
- 如何设计登录接口,十分钟内连续登录5次失败,需要等待30分钟才能登录
正常业务里的实现不能这样搞,合适的方法是走缓存,比如使用redis,我当时就只有原生Java API能用,请大家把这个当成算法题来看待 常言道:字数越短问题越大. 今天阿里的面试官小哥哥让我实现一 ...
- c语言for循环多条件判断,解决在for循环内判断条件多次执行
最近遇到的这个问题,就是在for循环内if判断的条件会多次执行. 例如,在返回的30数据中,a条目是第7条则会进行30次判断,弹出29次查无数据,也就是要点击29次关闭alert,很是让人不爽. 有了 ...
- SQL解决去重问题(在线超10min中的人数等)
SQL解决去重问题(在线超10min中的人数等) 内容目录 SQL解决去重问题(在线超10min中的人数等) 一.描述 二.求解 1.思路1 2.思路2 三.牛客的SQL33:直播各科出勤率 一.描述 ...
- SQL反模式笔记17——用一条sql解决复杂问题
目标:检查sql查询次数 反模式:试图用一条sql解决复杂问题 结果是:性能很低,而且往往得到了一个笛卡尔积. 解决方案:分而治之 用多个sql得到数据,再进行整合.或者union多个sql的结果. ...
- 你真的会玩SQL吗?和平大使 内连接、外连接
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 创建存储过程时出现的This function has none of DETERMINISTIC, NO SQL解决办法
This function has none of DETERMINISTIC, NO SQL解决办法 创建存储过程时 出错信息: ERROR 1418 (HY000): This function ...
- This function has none of DETERMINISTIC, NO SQL解决办法
This function has none of DETERMINISTIC, NO SQL解决办法 创建存储过程时 出错信息: ERROR 1418 (HY000): This function ...
- 高手过招:用SQL解决环环相扣的刑侦推理问题(苏旭辉版本)
苏旭晖,网名 newkid,ITPUB 开发版资深版主,SQL开发专家 本文是继 杨长老 刑侦高考:如何用SQL解决环环相扣的刑侦推理问题 之后,苏旭辉的一个版本,希望大家能够在高手的过招中,看到喜 ...
- 高手过招:用SQL解决环环相扣的刑侦推理问题(罗海雄版本)
关注我们获得更多精彩内容! 本文是继 杨长老 刑侦高考:如何用SQL解决环环相扣的刑侦推理问题 之后(点击阅读原文查看历史信息),罗海雄老师提供了一个带注释的版本,希望初学者也能够直接看懂,不仅仅是 ...
最新文章
- beta阶段140字评论
- EOS 智能合约源代码解读 (4)symbol.hpp
- QT的QCache类的使用
- MFC载入JPG图片
- 作者:刘昂(1990-),男,中国科学院计算机网络信息中心工程师
- 程序员该如何合理安排时间呢?
- 【BZOJ-3721】Final Bazarek 贪心
- HTML5的设计目的是为了在移动设备上支持多媒体
- 怎么看待苹果公司要求分成微信、知乎打赏32%?
- mcgs 安装没有权限_我的电脑为什么不能安装mcgs组态软件
- 空间战场态势感知系统
- LTE IDLE DRX和CDRX
- iOS性能优化的几个方向
- confusion matix
- 蓝桥杯十大常见天阶功法——炎之呼吸.叁之型.动态规划--(上篇)
- 外币记账及重估总账余额表变化(下)
- 项目经理的能力模型和能力提升的方法
- 如何把项目部署到腾讯云服务器(附带常见错误)
- python爬取微信群聊内容_再不学Python 你就被同龄人甩开了吗?
- 使命召唤手游如何在电脑上玩 使命召唤手游模拟器教程
热门文章
- docker加了--insecure-registry后docker启动报错Failed to start Docker Application Container Engine.
- python判断正数负数_python 负数变正数
- 使用adb工具向android设备上传/下载文件
- java bss_数据段、代码段、堆栈段、BSS段的区别
- 坐标测量机的定位误差和测长不确定度有何区别,如何表示?
- 大家来找茬源码(微擎) -- 流量主
- showVideo C#版 摄像头驱动程序
- [渝粤教育] 西南科技大学 汉语写作 在线考试复习资料
- tzoj 3847 Mowing the Lawn (单调队列 )
- csgo 机器人模式_csgo怎么加机器人