查询满足连续任意30天的全量交易的多个商户

需求说明:

        先说表结构把,就是一张订单表存了商户号和其他相关信息,现在要查询这个订单表中以商户为主体的连续交易,也就是每天产生至少一笔订单的商户才算连续,不知道看到的小伙伴有没有什么想法和头绪,在一般的业务场景下可能不会有这个需求,但只有遇到了才想知道解决方案 当时这个需求背景是为应付某某检查所以才有这个需求,步入正题把 具体分析都写在sql中 不懂可以看看总结的难点,大家有场景可以试一试,一定是有多种写法的,这里我写出了两种,

最优写法:

-- with:创建临时查询命名的关键字
WITH consecutive_numbers (create_time,cust_no,group_id) AS (
  SELECT
  create_time,
  cust_no,
  -- 根据客户号分区再使用行号判断这段时间是否为连续数字,如果group_id是相同的说明就是连续的
  create_time - ROW_NUMBER() OVER (PARTITION BY cust_no ORDER BY create_time) AS group_id
  FROM (
    -- 去重意义:去重是为了保证每一天每个客户号的多笔交易的笔数只有一笔,并且使用DISTINCT去重
    -- 去重位置:只能套在子查询里去重
    -- 如果在子查询里可以使用DISTINCT to_char(t.create_time, 'yyyyMMdd')去重
    -- 也可以使用group by to_char(t.create_time, 'yyyyMMdd')去重
    
    -- 如果放在外面使用DISTINCT去重就会失效因为group_id字段是通过 ROW_NUMBER()计算出来的他在每一行有唯一的值
    -- 并且在外面使用group by去重也会报错因为group by的字段需要和查询的字段保持一致但是group by不支持ROW_NUMBER() 窗口函数
    SELECT DISTINCT
    to_char(t.create_time, 'yyyyMMdd') as create_time,
    cust_no
    FROM
    xxx.order_info t
    WHERE
    -- 这里可以指定多个商户号或是不指定查所有商户
    cust_no IN ('199900002007','199900004854')
  )
)
SELECT
    MIN(create_time) AS start_create_time,
    MAX(create_time) AS end_create_time,
		cust_no,
    COUNT(*) AS count
FROM
    consecutive_numbers
-- 对group_id,cust_no都相同的进行分组,在对分组里面的数据计算合计就能得到连续的条数count
GROUP BY
    group_id,cust_no
-- 这个判断就是判断连续的天数大于多少    
HAVING
    COUNT(*) >= 4;

 写法2

 select abc.* from (with t as
(select a.CUST_NO, a.createTime, b.createTime as snap2
from (select DISTINCT cust_no, to_char(CREATE_TIME,'yyyyMMdd') as createTime from xxx.order_info where order_status='00') a,
(select DISTINCT cust_no, to_char(CREATE_TIME,'yyyyMMdd') as createTime from xxx.order_info where order_status='00') b
where a.CUST_NO = b.CUST_NO(+)
and a.createTime - 1 = b.createTime(+)
order by CUST_NO, createTime),
t1 as
(select t.*,
case
when snap2 is null then
1
else
0
end as lxzt
from t
order by CUST_NO, createTime),
t2 as
(select t1.*, sum(lxzt) over(order by CUST_NO, createTime) as fzyj
from t1
order by CUST_NO, createTime)
select CUST_NO,
--        fzyj,
((max(createTime)-min(createTime)) + 1) as 连续天数,
min(createTime) as start_snap,
max(createTime) as end_snap
from t2
where CUST_NO = '199900002007'
group by CUST_NO, fzyj
order by start_snap desc) abc;  

总结难点:判断连续性分析

实际上这里难点是如何判断一串数据是否具有连续性,如何将判断出的连续性结果应用在业务sql当中,这里再说明下连续性判断,举个简单例子 我这里有个表 id从1到2连续 从4到6连续  

通过这段sql可以得出,从哪开始到哪结束的连续,原理是一样的 因为id是依次增长,行号也是,所以他们相减如果是一样的 哪说明一定是连续的,再通过分组函数将相同的结果进行分组就能得到连续的数据,最后判断连续数的大小就能知道连续持续了多长

如果还有疑问的兄弟可以加我技术讨论群只纯粹讨论技术

📢 加入我们的Java技术交流群!

我们创建了一个专门针对Java技术爱好者的交流平台, 目的只是为了纯粹探讨技术难题 、分享心得与资源。无论您是初学者还是资深开发者,在这里都能找到志同道合的朋友!

🌟 群内特色:

专业讨论:专注于Java及相关技术栈的深度探讨;

互助成长:遇到问题时,总有人愿意伸出援手;

无广告环境:为了保持群内的纯净氛围,我们坚决抵制任何形式的广告行为。

👉 如何加入:

扫描下方二维码直接加入;

加入时请备注:[您的主要语言]+[从业年限](例如:Java 3年);

如果二维码已过期,请私信联系我获取最新入口。

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wrx繁星点点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值