SQL面试题62--一种准确求近30天消费金额的方法

news2024/9/22 3:53:21

1 需求

现在test表有三个字段 用户: user_id 日期:dt 订单金额 price,

计算出一个消费者历史上“首次”在近30天周期内累计消费金额达到1W的日期

2 分析

  

(1)数据准备

 create table test as 
 select 'a' as user_id,7000 as price,'2022-07-01' as dt
    union all 
   select 'a' as user_id,4000 as price,'2022-08-22' as dt
   union all 
   select 'a' as user_id,8000 as price,'2022-08-23' as dt

(2) 分析

目标字段:消费者,日期

条件:首次”在近30天周期内累计消费金额达到1W的日期

第一步:如何求近30天周期内累计消费金额

一般此类问题我们容易想到如下解法

sum(price) over(partition by user_id order by dt rows between prceding 30 and current row)

但是改解法有个问题,我们采用rows的时候计算的是实际物理行数,但是实际数据中用户的时间并不是连续的,也就是存在时间断层或缺失的现象,此时用rows计算的实际结果则会偏大,显然不对。而对于hive的计算引擎提供了,range计算方法,他表示的是排序行的逻辑计算值,并在此范围内的所有数据,即[dt -30,dt],刚好反应了所要表达的意思,近30天的结果。因此可以按照如下求法

sum(price) over(partition by user_id order by cast (dt as date) range between prceding 30 and current row)

第二步:求首次日期 

首次:min(dt) --最早

拓展:最近、最新、末次日期max(dt)

完整的SQL如下:

select user_id,min(dt)
from (
         select dt
              , user_id
              , sum(price)
                over (partition by user_id order by cast(dt as date) range between 30 preceding and current row) as order_price
         from (select 'a' as user_id, 7000 as price, '2022-07-01' as dt
               union all
               select 'a' as user_id, 4000 as price, '2022-08-22' as dt
               union all
               select 'a' as user_id, 8000 as price, '2022-08-23' as dt
              ) t
     ) t
where order_price > 10000
group by user_id

对比rows求得结果:

select user_id, min(dt)
from (
         select dt
              , user_id
              , sum(price)
                over (partition by user_id order by dt rows between 30 preceding and current row) as order_price
         from (select 'a' as user_id, 7000 as price, '2022-07-01' as dt
               union all
               select 'a' as user_id, 4000 as price, '2022-08-22' as dt
               union all
               select 'a' as user_id, 8000 as price, '2022-08-23' as dt
              ) t
     ) A
where order_price > 10000
group by user_id

明显rows求得的结果不对,2022-07-01日期就不在2022-08-22近30天日期范围内

中间结果如下:

对于有的数据库没有range函数的,此时如何求呢?我们可以借助时间维度表去补全日期数据,这也是常见的通用方法,比如我们有一张日期全的维度表dim_date

可以看出日期是连续的,由于partition by 后需要按照用户(user_id)分组,所以用户的维度需要补齐在时间维度表中,这种补齐维度的操作我们一般采用自关联SQL如下:

with data as
         (select 'a' as user_id, 7000 as price, '2022-07-01' as dt
          union all
          select 'a' as user_id, 4000 as price, '2022-08-22' as dt
          union all
          select 'a' as user_id, 8000 as price, '2022-08-23' as dt
         )
,dim_user AS
    (select 'a' user_id
     UNION ALL
     select 'b' user_id
     UNION ALL
     select 'c' user_id
    )
select *
from
(     select d.date_id, u.user_id
               from (select date_id
                     from dim.dim_date
                     where date_format(date_id, 'yyyy-MM') >= '2022-06'
                    ) d,
                    dim_user u
              ) d
             

具体结果如下:

可以看出每个时间记录上,都得到了相应用户的维度值。

最后我们用该表作为主表left join数据表,通过关联条件将数据唯一对应过来

with data as
         (select 'a' as user_id, 7000 as price, '2022-07-01' as dt
          union all
          select 'a' as user_id, 4000 as price, '2022-08-22' as dt
          union all
          select 'a' as user_id, 8000 as price, '2022-08-23' as dt
         )
,dim_user AS
    (select 'a' user_id
     UNION ALL
     select 'b' user_id
     UNION ALL
     select 'c' user_id
    )
select *
from
(     select d.date_id, u.user_id
               from (select date_id
                     from dim.dim_date
                     where date_format(date_id, 'yyyy-MM') >= '2022-06'
                    ) d,
                    dim_user u
              ) d
              left join data
on d.date_id = data.dt and d.user_id=data.user_id

具体结果如下:

我们可以看到主表是比较全的维表,拥有所有的时间、用户属性,order by 后的日期应该是维表中的日期,partition by后的user_id应该为主表中的user_id,此时再用rows 求解就没有问题。

最终SQL如下:

with data as
         (select 'a' as user_id, 7000 as price, '2022-07-01' as dt
          union all
          select 'a' as user_id, 4000 as price, '2022-08-22' as dt
          union all
          select 'a' as user_id, 8000 as price, '2022-08-23' as dt
         )
,dim_user AS
    (select 'a' user_id
     UNION ALL
     select 'b' user_id
     UNION ALL
     select 'c' user_id
    )
select user_id, min(dt)
from (
         select dt
              , d.user_id
              , sum(price)
                over (partition by d.user_id order by d.date_id rows between 30 preceding and current row) as order_price
         from (
               select d.date_id, u.user_id
               from (select date_id
                     from dim.dim_date
                     where date_format(date_id, 'yyyy-MM') >= '2022-06'
                    ) d,
                    dim_user u
              ) d
              left join data
            on d.date_id = data.dt and d.user_id=data.user_id
     ) A
where order_price > 10000
group by user_id

可以看出最终求解的结果值和range的结果是一致 的。

小结:是否需要补全其他维度值,看partition by后的分组字段,有多少个就需要补全哪些,因为直接用时间维度表做主表,partition by无法正确分组,需要补全 后面的分组字段才行。改方法性能上肯定比较差,但也是比较通用的方法,对于一些窗口不支持range子句的则也只能采取这样的方法。

3 小结

本文讲解了一种求近30天消费金额的方法,给出了2种思路,2种方法都比较通用,都需要掌握。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据分析很火吗?千万不要轻易尝试!

据说数据分析现在很火?“现在是数字化时代,工作生活都是与互联网交织在一起,我们的生活习惯、兴趣爱好等都会演变成各种不同的数据被互联网收集存储(云存储)。作为个人而言这些数据单看的话是没有什么价值和意义的&…

安全卫“视”!昂视助力极片卷绕对齐度检测

价格大涨、产能扩充、加速融资、加快出海、与车企深度绑定,动力电池产业在2022年表现出了极高的市场活力,在疫情的大环境之下,其发展势头是业内外公认的“高亢”。全国乘用车市场信息联席会预计,2023年新能源乘用车销量有望达850万…

SCI论文阅读-深度学习在测井气体红外光谱定量分析中的应用

期刊: Applied Optics中科院最新分区(2022年12月最新版):4区影响因子(2021-2022):1.905第一作者:宋丽梅通讯作者:Yangang Yang原文链接:Application of deep …

一文弄懂什么是对比学习(Contrastive Learning)

本文是自己学习对比学习的总结,如有问题,欢迎批评指正。 前言 有的paper将对比学习称为自监督学习(Self-supervised learning),有的将其称为无监督学习(Unsupervised Learning , UL)。自监督学…

spring事务执行流程分析_6(事务的真正执行)

代理对象的执行 执行案例中的bookService.addUser(user);会调用到JdkDynamicAopProxy#invoke方法 JdkDynamicAopProxy#invoke public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy null;boolean setProxyContext false;…

2023年黑马Java入门到精通教程--编程思维训练

编程案例分享 编程思维 使用所学的Java技术解决问题的思维方式和编写代码实现出来的能力。 关于提升编程思维和编程能力的建议 编程思维和编程能力不是一朝一夕形成的,需要时间的沉淀和大量练习。 前期:先模仿,后期:再创新。…

为游戏玩家提供卓越价值,英特尔锐炫游戏性能大幅提升!

2月1日晚英特尔推出锐炫显卡新版驱动(4086),相较此前驱动(3490)能够为DirectX 9游戏带来40%以上的平均性能提升。同时英特尔还宣布,现在起锐炫A750限量版显卡的全球价格将调整为249美元,此前上市价格为289美元起。 在英特尔发布锐炫显卡后&…

HTML5+CSS3(五)-全面详解(学习总结---从入门到深化)

目录 容器元素&#xff08;div&#xff09; 学习效果反馈 HTML5新增布局标签 学习效果反馈 视频和音频 视频 音频 source 学习效果反馈 HTML5新增标签 figure details mark meter datalist canvas 学习效果反馈 容器元素&#xff08;div&#xff09; <!DOCTYPE h…

k8s核心资源存储对象

一、简介 和docker类似&#xff0c;k8s也需要存储数据&#xff0c;比如redis和mysql都需要外部存储对象&#xff0c;要不然重新拉起pod&#xff0c;在其他机器上数据会消失。 二、NFS共享存储 NFS这个文件系统提供了远程挂载共享数据&#xff0c;我们可以利用这个文件系统来…

ASEMI整流模块MDA300-16封装,MDA300-16大小

编辑-Z ASEMI整流模块MDA300-16参数&#xff1a; 型号&#xff1a;MDA300-16 最大重复峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;1600V 最大RMS电桥输入电压&#xff08;VRMS&#xff09;&#xff1a;1700V 最大平均正向整流输出电流&#xff08;IF&#xff0…

408计组巅峰之路:总线技术、总线仲裁

文章目录总线概念总线的基本概述总线分类标准①按数据传输格式②按总线功能&#xff08;连接的部件&#xff09;③按时序控制方式微机总线&#xff08;补充&#xff09;性能指标典型的计算机总线1.个人计算机总线测控机箱底板总线仪器与计算机互联总线PCI 总线局部总线1.PCI总线…

单片机复位详解

复位&#xff08;stm32f407ZGT6&#xff09;-属于中断操作共有三种类型的复位&#xff0c;分别为系统复位、电源复位和备份域复位。系统复位除了时钟控制寄存器 CSR 中的复位标志和备份域中的寄存器外&#xff0c;系统复位会将其它全部寄 存器都复位为复位值。只要发生以下事件…

纹理贴图原理与实践【图形学基础】

纹理贴图是 20世纪90 年代 CG 的主要创新之一。 它允许我们在不添加大量几何基元&#xff08;线、顶点、面&#xff09;的情况下添加大量表面细节。 想一想 Caroline 的 loadedDemo 的所有纹理映射是多么有趣&#xff1a; 推荐&#xff1a;使用 NSDT场景编辑器 快速搭建 3D场景…

树的重心(树和图的遍历--dfs)

树和图的存储&#xff1a; 定义h[N]&#xff0c;用来存储多个head指针。然后利用单链表的思想将数字插入进去。 void add( int a , int b ) { e[idx]b , ne[idx]h[a] , h[a]idx; } -----------------------------------------------------------------------------…

什么是类?怎样声明类的继承关系?

在现实生活中&#xff0c;说到继承&#xff0c;多会想到子女继承父辈的财产、事业等。在程序中&#xff0c;继承描述的是事物之间的所属关系&#xff0c;通过继承可以使多种事物之间形成一种关联体系。例如猫和狗都属于动物&#xff0c;程序中便可以描述为猫和狗继承自动物&…

从零开始的数模(十二)时间序列

目录 一、概念 1.2方法 二、基于python的时间序列 2.1移动平均法 2.2指数平滑法 2.3灰色预测 2.4灰色关联 2.5ARIMA模型 模型系 三、 基于matlab的时间序列 3.1移动平均法 3.2指数平滑法 一次指数平滑法 二次指数平滑法 一、概念 1.1带有时间的数据有哪些特殊性 带…

OAuthApp v2.2.3 更新 | 前端发布工具

OAuthApp 是一个前端发布工具&#xff0c;用于快速开发前端网页项目&#xff0c;并发布到服务器。具有引入脚本库就能使用服务端 API、在线发布 H5、站点数据独立存储的特性。 2023-2-3 主要更新 1&#xff0c;[修复] 站点文件功能&#xff0c;上传图片报错。 2&#xff0c;[新…

某FPS游戏飞天辅助及原理

FPS游戏先天的竞技性以及对战性决定了他必然有很多的BUG可以被利用又必须的去检测解决。 FPS游戏中有这样的外挂&#xff0c;飞在高空中打敌人,因为很少有人会注意头顶 躲在墙壁中攻击敌人&#xff0c;敌人根本无法看到高空墙壁中的人物。 那么胜利就很简单了。 FPS游戏能够…

4000字IB EE论文该怎么解决?

IB课程的Extend Essay&#xff0c;即EE拓展论文&#xff0c;是一篇基于六门学科课程的论文&#xff0c;需要学生在一年左右的时间里&#xff0c;完成一篇将近4000字&#xff08;中文为4800字&#xff09;的论文。该论文与某一门IB学科组课程相关。学生在论文中要体现自己对这门…

Windows Server 2022 Install Veeam Backup 12

Veeam Backup & Replication 是一款可靠的四合一解决方案&#xff0c;将备份、复制副本、存储快照和 CDP 复制副本统一在一款可靠的数据保护解决方案下&#xff0c;可助力实现数据保护现代化并消除停机。通过有效的勒索软件防护实现更快速、更灵活的恢复和保留选项&#xf…