前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何删除相邻连续的重复行?

如何删除相邻连续的重复行?

作者头像
猴子数据分析
发布2022-07-13 17:15:03
4.5K0
发布2022-07-13 17:15:03
举报
文章被收录于专栏:猴子数据分析

【题目】

如下为一张互联网企业用户访问商城的各页面的访问记录表

要求当用户连续访问同一页面时,只保留第一次访问记录,即得到如下结果:

字段说明:

用户ID:用户的账户

访问的页面:用户访问商城时查看的页面

访问页面时间:用户打开该页面的时间点

【解题思路一】:

根据题意的要求,把要求的结果在原表上用黄色标出,通过观察发现连续登录的某一个页面只保留第一次访问的记录。解题思路是要通过查询,利用信息差过滤掉同一个页面第一次登录后的连续访问记录。

1、利用自联结,得到两张相同的表,t1作为主表,t2作为从表,左联结2张表,并都按照用户分组,按照用户的访问时间升序排序

代码语言:javascript
复制
(select
用户ID
,访问的页面
,访问页面时间
,row_number() over (partition by 用户ID order by 访问页面时间 asc) as 访问序号
from 访问记录表)t1
left join
(select
用户ID
,访问的页面,访问页面时间
,row_number() over (partition by 用户ID order by 访问页面时间 asc) as 访问序号
from 访问记录表)t2
on t1.用户ID=t2.用户ID

2、制造信息差

因为要过滤掉同一个页面第一次登录后的访问记录,即要判断用户第一次访问的页面与后面第二次访问页面是否相同,即“t1的访问序号=t2的访问序号+1”。

代码语言:javascript
复制
(select
用户ID,访问的页面,访问页面时间
,row_number() over (partition by 用户ID order by 访问页面时间 asc) as 访问序号(与图片中的列名不一致)
from 访问记录表)t1
left join
(select
用户ID,访问的页面,访问页面时间
,row_number() over (partition by  用户ID order 访问页面时间  asc) as 访问序号
from 访问记录表)t2
on t1.用户ID=t2.用户ID
and t1.访问序号=t2.访问序号+1

3、取出符合条件的记录

在第2步的基础上加上筛选条件,即当t1的访问序号=t2的访问序号+1时,t1.访问的页面!=t2.访问的页面。另外,还需要考虑到增加一个条件 “t2.访问的页面 is null“,因为当t1=1时,t2是空值,要把t1=1取出,必须加上条件“t2.访问的页面 is null“。只有”t1.访问的页面!=t2.访问的页面“一个条件,会漏掉主表的第1条页面的记录。如上图所示

代码语言:javascript
复制
select
t1.用户ID
,t1.访问的页面
,t1.访问页面时间
from
(select
用户ID
,访问的页面
,访问页面时间
,row_number() over (partition by 用户ID order by 访问页面时间 asc) as 访问序号
from 访问记录表) t1
left join
(select
用户ID
,访问的页面
,访问页面时间
,row_number() over (partition by  用户ID order by访问页面时间  asc) as 访问序号
from 访问记录表) t2
on t1.用户ID=t2.用户ID
and t1.访问序号=t2.访问序号+1
where t2.访问的页面 is null
or t1.访问的页面!=t2.访问的页面;

运行结果为:

【本题考点】

1、自联结。本题利用自联结,获得信息差。自联结是指使用表的别名实现表与其自身联结的查询方法。我们需要对一张表内的数据,进行一些对比,或者是比较,获得各列层次关系,通过一般的SQL写法,可能需要通过写多个子查询的方式才能解决。但是用自联结查询可以轻松解决,自联结查询就是以类似多表对比的方式,实现对同一张表内数据进行复杂的关系表示或关系处理。关键点在于虚拟化出一张表给一个别名。自联结得到的查询结果比较直观但是不适合操作大表,容易产生笛卡尔积,造成数据量巨大。

2、窗口函数排序

row_number()在SQL语句中非常的重要的窗口函数,一般与partition by,order by连用,组成

代码语言:javascript
复制
row_number() over (partition by … order by … )

表示按照某个字段分组,按照某个字段的值来排序的顺序。详细用法见窗口函数的介绍。

【解题思路二】:

上面的操作步骤比较清晰和简单,但是感觉比较啰嗦,还有一种比较简洁的做法,利用lag()函数增加一列“上一个访问的页面”,利用本次访问的页面不等于上一个访问的页面作为条件,取出要求的结果,思路与第一个思路一致。

代码语言:javascript
复制
select
t.用户ID
,t.访问的页面
,t.访问页面时间
from
(select
用户ID
,访问的页面
,访问页面时间
,lag(访问的页面,1,0) over (partition by 用户ID order by 访问页面时间 asc) as 上一个访问的页面
from 访问记录表)t
where t.上一个访问的页面 is null
or t.访问的页面!=t.上一个访问的页面

【本题要点】

此种解法用到了lag()函数,lag()函数是查询当前行向上偏移n行对应的结果 该函数有三个参数:第一个为待查询的参数列名,第二个为向上偏移的位数,第三个参数为超出最上面边界的默认值。,一般与over()连用,为窗口函数的一种。

代码语言:javascript
复制
lag(…) over (partition by… order by…)

下图为lag()函数向上偏移一行,两行,并超出边界用“0”表示的图示。

【此面试题的总结】:

此题重点考察的是计算逻辑和窗口函数。怎么理解数据,并取出需要的行数,需要很强的逻辑思路,属于面试题中比较难的题目。逻辑思路正确是写正确代码的前提。一个题目有多种实现的方式,不是只有一种代码可以实现,遇到问题换个思路和解法,多写多练就能很快的提高。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猴子数据分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档