当前位置: 首页 > article >正文

SQL练习专场--01

在这个专场中,会陆续更新一些关于sql的面试题

-- 题目1:【*】找出连续活跃3天及以上的用户

建表语句:

create table t_useractive(
  uid   string,
  dt    string
);

insert into t_useractive
values('A','2023-10-01'),('A','2023-10-02'),('A','2023-10-03'),('A','2023-10-04'),
      ('B','2023-10-01'),('B','2023-10-03'),('B','2023-10-04'),('B','2023-10-05'),
      ('C','2023-10-01'),('C','2023-10-03'),('C','2023-10-05'),('C','2023-10-06'),
      ('D','2023-10-02'),('D','2023-10-03'),('D','2023-10-05'),('D','2023-10-06');

解题思路:

先使用排名函数row_number给dt的值日期进行排序,通过data_sub()方法相减,若得到的日期相同,那么可以说明,这些时间就是连续登录的了。

最后在根据pm的值进行count(),如果列数大于3,就证明是连续三天登录的

sql代码如下:

select * from t_useractive;
-- 第一步,先将字符串类型的dt转成日期类型(其实在这题中,不转换也可以)
select uid,date_format(dt,'yyyy-MM-dd') dt from t_useractive group by uid,dt;
-- 第二步,使用row_number函数对每个用户的登录时间进行一个排名,然后使用日期减去这个排名,若得到的日期相同,那么可以说明,这些时间就是连续登录的了。
with t as (
    select uid,date_format(dt,'yyyy-MM-dd') dt from t_useractive group by uid,dt
),t2 as (
    select *, date_sub(dt, row_number() over (partition by uid order by dt)) pm from t_useractive
) select uid from t2 group by uid, pm having count(1) >= 3;

结果:

复习排名函数:

1、row_number()

row_number从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列

效果如下:
98                1
97                2
97                3
96                4
95                5
95                6

没有并列名次情况,顺序递增
2、rank()

生成数据项在分组中的排名,排名相等会在名次中留下空位

效果如下:
98                1
97                2
97                2
96                4
95                5
95                5
94                7
有并列名次情况,顺序跳跃递增
3、dense_rank()

生成数据项在分组中的排名,排名相等会在名次中不会留下空位

效果如下:
98                1
97                2
97                2
96                3
95                4
95                4
94                5
有并列名次情况,顺序递增

题目2:统计每个Top3歌单以及Top3歌单下的Top3歌曲

表中数据如下:

1   1  经典老歌    1   月亮代表我的心
2   1  经典老歌    1   月亮代表我的心
3   1  经典老歌    3   夜来香
4   1  经典老歌    4   我只在乎你
5   1  经典老歌    5   千言万语
6   1  经典老歌    5   千言万语
7   2  流行金曲    7   突然好想你
8   2  流行金曲    8   后来
9   2  流行金曲    9   童话
10  2  流行金曲    10  晴天
11  2  流行金曲    7   突然好想你
12  2  流行金曲    7   突然好想你
13  3  纯音乐集    13  二泉映月
14  3  纯音乐集    14  琵琶语
15  3  纯音乐集    15  梦回还
16  4  欧美音乐    16  Shape of My Heart
17  4  欧美音乐    17  Just the Way You Are
18  4  欧美音乐    18  Hello
19  4  欧美音乐    19  A Thousand Years
20  4  欧美音乐    20  Thinking Out Loud
21  4  欧美音乐    20  Thinking Out Loud
22  4  欧美音乐    18  Hello
23  4  欧美音乐    18  Hello
24  5  民谣时光    24  易燃易爆炸
25  5  民谣时光    25  成全
26  5  民谣时光    25  成全
27  5  民谣时光    25  成全

建表语句以及导入语句:

现在本地集群的 /home/sqltest 下创建一个est03.txt,将上面的数据放进去,再执行以下语句,完成数据导入

create table songs(
  uid int,
  lid int,
  list_name string,
  sid int,
  song_name string
)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties(
  'input.regex'='([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+(.*)'
   ,"output.format.string" = "%1$s %2$s %3$s %4$s %5$s"
);


load data local inpath '/home/sqltest/test03.txt' into table songs;

sql如下:

-- 统计每个Top3歌单以及Top3歌单下的Top3歌曲
-- 思路:先统计top3歌单
select list_name,count(1) list_songsNum from songs group by list_name order by list_songsNum desc limit 3;

-- 再根据top3歌单挑选出所有的歌曲进行数量记录 (通过join)
with t as (
    select list_name,count(1) list_songsNum from songs group by list_name order by list_songsNum desc limit 3
) select s.list_name,s.song_name,count(1) songsNum from t join songs s on t.list_name = s.list_name group by s.list_name,s.song_name;

-- 最后,使用排名函数排名,取排名前三名的即可
with t as (
    select list_name,count(1) list_songsNum from songs group by list_name order by list_songsNum desc limit 3
) ,t2 as (
    select s.list_name,s.song_name,count(1) songsNum from t join songs s on t.list_name = s.list_name group by s.list_name,s.song_name
) ,t3 as (
    select list_name,song_name,rank() over (partition by list_name order by songsNum desc) pm from t2
)select * from t3 where pm <= 3

如果这里使用的是row_number() 排序函数的话,就会产生下面的结果,可能会丢失数据

(row_number()的值不会存在重复)

第三题总结:先根据表,求出top3的歌单,再使用join使临时表与原表关联,得出top3歌单下的所有歌曲信息,然后再使用聚合函数得出每个歌曲的数量多少,之后根据排名函数给歌曲排名,得到前三歌单的歌曲

题目3:【*】用一条sql语句查询出每门课都大于或等于80分的学生姓名

建表语句以及sql语句如下:

create table t1(
     name   string,
     course string,
     grade  int
);

INSERT INTO t1 (name, course, grade) VALUES
('张三', '英语', 85),
('张三', '语文', 90),
('张三', '数学', 92),
('李四', '英语', 75),
('李四', '语文', 98),
('李四', '数学', 72),
('王五', '英语', 90),
('王五', '语文', 85),
('王五', '数学', 92),
('王五', '体育', 80);
select * from t1;
-- 用一条sql语句查询出每门课都大于或等于80分的学生姓名
select name,min(grade) minScore from t1 group by name having minScore > 80;

先更新这么几道,后续会接着更新更多


http://www.kler.cn/a/383089.html

相关文章:

  • 【Rust自学】5.3. struct的方法(Method)
  • Redis篇--常见问题篇6--缓存一致性1(Mysql和Redis缓存一致,更新数据库删除缓存策略)
  • CSPM认证最推荐学习哪个级别?
  • aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发
  • Java基于SSM框架的无中介租房系统小程序【附源码、文档】
  • PostgreSQL标识符长度限制不能超过63字节
  • 【glm4-voice-9b 本地运行并测试 gradio+notebook】
  • 探索空间计算与 VR 设备的未来:4K4DGen 高分辨率全景 4D 内容生成系统
  • ssm061基于SSM框架的个人博客网站的设计与实现+vue(论文+源码)_kaic
  • AI 搜索来势汹汹,互联网将被颠覆还是进化?
  • Openlayers高级交互(20/20):超级数据聚合,页面不再混乱
  • 使用 Let’s Encrypt 获取免费SSL证书
  • 城镇住房保障系统:SpringBoot开发要点
  • TLU - Net:一种用于钢材表面缺陷自动检测的深度学习方法
  • c语言架构的一点构想
  • 挂钩图像分割安全状态与危险状态识别系统:更新创新流程
  • 推荐一款可视化和检查原始数据的工具:RawDigger
  • Midjourney从入门到精通教程,10分钟让你从小白变大神!【珍藏版】
  • Bert完形填空
  • Java基础使用①Java特点+环境安装+IDEA使用
  • 求猫用宠物空气净化器推荐,有没有吸毛强、噪音小的产品
  • Linux awk命令详解-参数-选项-内置变量-内置函数-脚本(多图、多示例)
  • 我们来学mysql -- EXPLAIN之ID(原理篇)
  • 爱普生 SG - 8201CJA 可编程振荡器成为电子应用的解决方案
  • 【LeetCode】【算法】142. 环形链表II
  • 开放寻址法、链式哈希数据结构详细解读