SQL大厂春招真题,独家详细解析

大家好,我是宁一。

SQL不仅仅是每个技术开发必须掌握的技能,

也是数据分析、商业分析招聘中,必考的能力。

这次给大家整理了SQL大厂春招的真题,每道题都加了独家详细解析。

整理完后,我的脑袋是蒙蒙的。

大厂就是大厂,这个烧脑程度,拜服!


之前也出过一篇大厂实战真题,大家可以一起食用。

2022年SQL大厂高频实战面试题(详细解析)

刷完这些题,相信大家能找到大厂出题的规律,大厂比较重视综合能力,题目不会只考一个知识点。

比如大多题目都综合考察了聚合函数、窗口函数、嵌套查询、索引、日期函数等知识点。

所以我们各个知识点都要熟练掌握。

这周六(3月26日)我会出SQL入门进阶课程。

不是广告,自己写的,免费的~

打算用最直白的语言给大家讲清楚SQL。从小白的角度入手,手把手教你学习SQL的入门以及进阶知识。

有些同学可能看过我之前的小程序实战课程,知道我的讲课风格就是:不说废话,只讲干货。

从最基础的增删改查,到进阶的视图、触发器、事件、事务等都会涉及。实战举例+作业巩固,争取用一门课让大家掌握SQL,可以顺利面试、参与工作。

感兴趣的同学可以关注蹲一下哦~

下面是大厂春招真题:

一、嵌套查询

嵌套查询,顾名思义,就是查询语句的嵌套,即在外部查询中还包含一个内部查询。

内部查询也叫子查询,查询结果可以作为一个临时表来使用,完成更为复杂表联结数据的检索功能。

嵌套查询是由内而外进行分析,子查询的结果作为主查询的查询条件。子查询中一般不使用order by子句,只能对最终查询结果进行排序。

经典问题:

下面表格是用户访问表users,记录了用户id(usr_id)和访问日期(log_date),查询出每个用户最近一次的登录记录和每个用户登录总次数(同一天多次登录认为是一次)。


实例结果:

解题思路:

根据示例结果,第二列current_day,是每个用户访问日期的最大值,直接用MAX聚合函数就可以。

第三列sum_day是每个用户登录总次数,因为同一天多次登录认为是一次,所以通过将原表log_date列格式化去掉时间,得出用户登录的日期,比如2021-05-03 01:00:08 格式化成 2021-05-03。我们就可以将日期去重,得到每个用户的登录总次数。

第一步:先将原表log_date列,通过DATE_FORMAT函数,进行日期的格式化。
SELECT
  usr_id,
  log_date,
  DATE_FORMAT(log_date,'%Y-%m-%d') AS days
FROM Users

第二步:再根据第一步得到的结果,将数据通过usr_id分组,并通过MAX聚合函数得到每组log_date列的最大值(也就是最近一次登录日期),通过COUNT聚合函数,得到用户登录总次数。
SELECT usr_id,
  MAX(log_date) AS current_day,
  COUNT(DISTINCT days) AS sum_day
FROM(
  SELECT
    usr_id,
    log_date,
    DATE_FORMAT(log_date,'%Y-%m-%d') AS days
  FROM Users
) AS a
GROUP BY usr_id;

二、大厂综合考察真题

这道题涵盖的知识点很多,包括索引、日期函数、聚合函数、窗口函数、嵌套查询。

能做出来,说明SQL掌握的已经很棒了,可以放心去面试。

经典问题:

我们现在有一个数据表DateTable,如下:

问题一:对数据表DateTable的dates列添加索引。

问题二:通过SQL语句,输入下方结果。

问题一:

这个就是考察索引语法的,很简单。

给DateTable表的dates列添加一个名为index_date的索引

CREATE INDEX index_date ON DateTable(dates);

查看索引

SHOW INDEX FROM DateTable;

问题二:

解题思路:

我们查看输出结果,第一列是年,第二列是月,这两列直接用日期函数就可以得到。

第四列,是将cost列按年汇总,第五列是将cost列全部汇总,因为每一行都有汇总记录,所以我们不应该单纯用聚合函数SUM来计算,而是用窗口函数+聚合函数SUM。

第一步:我们先将前三列查询展示出来。
SELECT dates,
  YEAR(dates) AS years,
  MONTH(dates) AS months,
  SUM(cost) AS cost
FROM DateTable
GROUP BY dates

第二步:再根据第一步得到的结果,通过聚合函数SUM,结合窗口函数得到四五列。对窗口函数不了解的盆友,可以点击上一篇文章了解~
SELECT years,months,cost,
SUM(cost) OVER(PARTITION BY years ORDER BY months) ysum,
SUM(cost) OVER(ORDER BY dates) sum
FROM(
  SELECT dates,
    YEAR(dates) AS years,
    MONTH(dates) AS months,
    SUM(cost) AS cost
  FROM DateTable
  GROUP BY dates
) AS a

在这里插入图片描述

可以使用下方语句快速建表测试:

create table DateTable (
dates datetime,
cost int
);
insert into DateTable values
("2020/07/12",10),
("2020/11/30",3),
("2019/2/9",20),
("2019/3/31",23),
("2022/2/8",99),
("2021/7/31",10);

三、字节春招真题

经典问题:

查询支付日期在2022.3.20之后的购买商品超过一次的用户,按照最新购买时间倒叙排列。

解题思路:

先找出2022.3.20之后的数据记录,再将这些记录根据user_id进行分组,通过COUNT聚合函数查出每组条数大于1的记录,最后还要按照最新购买时间倒叙排列。

SELECT user_id
FROM Products
WHERE purchase_date>"2022-03-20"
GROUP BY user_id
HAVING COUNT(*)>1销售
ORDER BY max(purchase_date) desc


这道题看着很简单,但是里面埋了几个陷阱需要注意:

  • having作用和where差不多,用来在分组之后,筛选分组才产生的数据。having后面可以直接跟聚合函数,如果要跟字段的话,这个字段必须在select后面提到过,where则不用

  • MySQL中,在使用聚合函数的时候,select后面的字段,必须出现在group by的后面,比如这道题中的user_id字段。

  • MySQL中,在使用聚合函数的时候,order_by后面的语句要注意使用聚合函数的字段,或者group by后面的字段。

上面的字段使用不太了解,没关系,我们来讲讲当一个查询语句同时出现where,group by,having,order by的时候,执行顺序和编写顺序,你就明白了。

FROM --> WHERE --> GROUP BY --> SELECT --> HAVING --> ORDER BY

我们再结合上面的题目看一下执行顺序:

1.执行where 语句对全表数据做筛选,FROM Products WHERE purchase_date>"2022-03-20”,返回第1个结果集。

2.针对第1个结果集使用group by分组,GROUP BY user_id,返回第2个结果集。

3.针对第2个结果集中的每1组数据执行SELECT user_id,有几组就执行几次,返回第3个结果集。

4.针对第3个结集执行HAVING COUNT(*)>1进行筛选,返回第4个结果集。

5.最后针对第4个结果集排序,ORDER BY max(purchase_date) desc

四、拼多多春招真题

经典问题:

现在有一个订单表orders,包括订单id(Oid)、商品id(product_id)、销售渠道(channel)、订单量(amount)。我们根据这个表,选取订单量前4的商品,并且选出每个商品订单量排名前2的销售渠道。

示例结果:

解题思路:

根据题目以及示例结果,我们最终要得到订单量最高的4个产品,以及每个产品对应排名前2的销售渠道。

我们可以先得到订单量排名前4的结果集1,再得到每个商品对应销售渠道的订单量排名结果集2,通过join将结果集1和结果集2连接得到最终结果。

第一步:首先获得订单量前4的商品,GROUP BY将产品分组之后,我们通过聚合函数SUM来获得每个产品的总订单量,命名为amt,再将amt倒序排序,通过limit 4得到订单量前4的商品。
SELECT product_id,
  SUM(amount) AS amt
FROM Orders
GROUP BY product_id
ORDER BY amt desc
LIMIT 4

第二步:我们再得到每个商品对应销售渠道的订单量排名
SELECT product_id,
  channel,
  ROW_NUMBER() OVER(PARTITION BY product_id ORDER BY amount DESC) AS rk
FROM Orders

第三步:将第一步和第二步的结果通过product_id列进行join链接,并限定条件第二步得到的rk排名列<=2。最终结果如下:
SELECT b.product_id,b.channel
FROM(
  SELECT product_id,
    SUM(amount) AS amt
  FROM Orders
  GROUP BY product_id
  ORDER BY amt desc
  LIMIT 4
) AS a
JOIN (
  SELECT product_id,
    channel,
    ROW_NUMBER() OVER(PARTITION BY product_id ORDER BY amount DESC) AS rk
  FROM Orders
) AS b
ON a.product_id = b.product_id
WHERE b.rk <=2

五、美团春招真题

现在有一个Products表,推荐出每个user_id,和他相似的用户所购买过的product。

要求:该用户已经购买过的不再推荐。

相似用户的定义:曾经购买过2种或2种以上的相同商品。

示例结果:

解题思路:

这道题我们先找出相似的用户,比如用户A和用户B是相似用户,我们需要将B购买过,而A没有购买过的产品推荐给A。这个跟实际业务很相似了,还需要费点脑筋的,我们来一步步拆解。

第一步:我们先找出相似的用户,也就是购买相同的商品>=2的用户。用到了自连接,找到不同用户对应相同商品的记录。再通过COUNT计算每个用户有多少条这样的记录。
SELECT a.user_id as uid_a,b.user_id as uid_b,
COUNT(DISTINCT b.product_id) as same_pro
FROM Products AS a
JOIN Products AS b
ON a.user_id != b.user_id 
AND a.product_id = b.product_id
GROUP BY uid_a,uid_b
HAVING same_pro>=2

第二步:将第一步得到的结果集,再通过uid_a连接Products表,连接条件是x.uid_a = y.user_id,这一步是为了得到product_id这一列。
SELECT x.uid_a,x.uid_b,y.product_id

FROM(
    SELECT a.user_id AS uid_a,b.user_id AS uid_b,
    COUNT(DISTINCT b.product_id) AS same_pro
    FROM Products AS a
    JOIN Products AS b
    ON a.user_id != b.user_id
    AND a.product_id = b.product_id
    GROUP BY uid_a,uid_b
    HAVING same_pro>=2
) AS x
JOIN Products AS y
ON x.uid_a = y.user_id

第三步:将第二步得到的结果集,再通过uid_b左连接Products表,连接条件是x.uid_b = z.user_id,y.product_id = z.product_id。

我们用的是左连接,即使不满足y.product_id = z.product_id,第二步获得的结果集也会全部显示,不满足条件的会显示null。这一步结果已经出来了,就是第四列为null 的记录。

SELECT x.uid_a,x.uid_b,y.product_id,z.product_id
FROM(
    SELECT a.user_id AS uid_a,b.user_id AS uid_b,
    COUNT(DISTINCT b.product_id) AS same_pro
    FROM Products AS a
    JOIN Products AS b
    ON a.user_id != b.user_id
    AND a.product_id = b.product_id
    GROUP BY uid_a,uid_b
    HAVING same_pro>=2
) AS x
JOIN Products AS y
ON x.uid_a = y.user_id
LEFT JOIN Products AS z
ON x.uid_b = z.user_id
AND y.product_id = z.product_id

在这里插入图片描述

第四步:根据第三步获得的结果集,我们判断第四列z.product_id为null,并且显示第二列x.uid_b和第三列y.product_id,就是最终的答案了。

最终结果如下:

SELECT x.uid_b AS user_id,y.product_id
FROM(
    SELECT a.user_id AS uid_a,b.user_id AS uid_b,
    COUNT(DISTINCT b.product_id) AS same_pro
    FROM Products AS a
    JOIN Products AS b
    ON a.user_id != b.user_id
    AND a.product_id = b.product_id
    GROUP BY uid_a,uid_b
    HAVING same_pro>=2
) AS x
JOIN Products AS y
ON x.uid_a = y.user_id
LEFT JOIN Products AS z
ON x.uid_b = z.user_id
AND y.product_id = z.product_id
WHERE z.product_id IS NULL;

六、快手春招真题

现在有主播表a:包括主播id(upid)、直播间id(rid)、开播时间(stime)
在这里插入图片描述
观众表b:包括观众id(uid)、进入的直播间id(rid)、进入时间(intime)

找出开播三分钟内无人进入的直播房间号。

解题思路:

我们先通过左连接,得到主播对应的3分钟进入直播间的观众,如果没有对应的观众,就是我们要找的记录。

第一步:将主播表a和观众表b进行左连接,条件是直播间id(rid)相同,并且主播开播时间(stime)大于(观众进入时间减去3分钟)。符合这个条件的主播,说明开播3分钟内有观众进入直播间。

比如主播是12:10分开播,观众在12:12分进入,这符合开播3分钟内进入的要求。

用数据表示就是:观众时间减去3分钟,是12:09分,12:10分>12:09分,说明用户在开播3分钟内进入直播间。

SELECT a.upid,a.rid,b.uid
FROM a
LEFT JOIN b
ON a.rid = b.rid
AND a.stime > date_add(b.intime,INTERVAL -3 minute)

在这里插入图片描述

第二步:第一步得到的结果集,第三列b.uid如果为null,说明这个直播间开播3分钟内没有观众进入。所以我们再添加一个where条件就可以了。
SELECT a.upid,a.rid
FROM a
LEFT JOIN b
ON a.rid = b.rid
AND a.stime > date_add(b.intime,INTERVAL -3 minute)
WHERE b.uid IS NULL;

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第二天 1、查询客户表,统计每个机构2000年之前开户数、2000~2005开户数(含头不含尾)、2005~2010开户数(含头不含尾)、2010之后开户数 展示字段:机构号、2000年之前开户数、2000~2005年开户数、2005~2010年开户数、2010年之后开户数 2、查询客户表,按年份统计,每年、每个机构开户数占全年开户数的占比 展示字段:年份、机构号、开户数、开户占比百分比(百分比) 3、统计所有客户的客户号、存款账户数、2011.12.31日的存款余额、2011.12存款月日均、贷款账户数、2011.12.31日的贷款余额、2011.12贷款月日均 备注:null置为0 第三天 1、统计所有客户的2011.12.31日的存款余额、存款比上日余额、存款比上月余额、、存款比上年余额 备注:存款比上日余额 = 2011.12.31日的存款余额-2011.12.30日的存款余额 存款比上月余额 = 2011.12.31日的存款余额-2011.11.30日的存款余额 存款比上年余额 = 2011.12.31日的存款余额-2010.12.31日的存款余额 只有2011.12.31这个日期可以写死,其他日期要通过2011.12.31这个日期来生成。 2、统计所有2011年存款年日均大于100的客户号、客户名称、存款账户数、2011年年日均 第四天 1、统计所有2011年存款年日均和2011年贷款年日均都大于100的客户号、存款账户数、2011年存款年日均、贷款账户数、2011年贷款年日均 2、统计所有客户的客户号、 存款标志(有存款账户的客户置为1、没存款账户的客户置为0)、 贷款标志(有贷款借据的客户置为1、没贷款借据的客户置为0)、 存款质量分类(2011年存款年日均>=10000置为优质、2011年存款年日均>=1000<10000 置为良好、2011年存款年日均=10000置为优质、2011年贷款年日均>=1000<10000 置为良好、2011年贷款年日均<1000置为普通)、 2011年贷款年日均 第五天 1、根据《事件表.xlsx》来建表,然后将excel中的数据导入到目标表中 2、根据客户表、存款信息表、事件表,统计每个客户2017年的客户号、 交易账户数(客户下有多少个账户有交易就是多少)、 当年有交易的天数(如果2017年有5天有过交易,则有交易天数为5)、 当年有交易总月数(如果2017的1、3、5月有交易,则有交易总月数为3)、 最大的月交易总金额(按月统计交易金额,存放最大的月交易金额)、 最大月交易金额的月份(按月统计交易金额,存放交易金额最大的月份)、 年总交易金额、 年交易金额排名(按客户排名,如果总交易金额为0,则不参与排名,排名置为9999)、 年总手续费、 年总手续费排名(按客户排名,如果总手续费为0,则不参与排名,排名置为9999)
C语言面试八股文是指在聘中常见的C语言相关的面试目和知识点。下面是一份常见的C语言面试八股文,供您参考: 1. C语言的基本数据类型有哪些? C语言的基本数据类型包括整型、浮点型、字符型和指针型。 2. 请介绍一下C语言中的变量和常量。 变量是用来存储数据的内存位置,可以通过变量名来访问和修改其值。常量是指在程序执行过程中不会改变的值。 3. 什么是数组?请介绍一下C语言中的数组。 数组是一种存储相同类型数据的集合,通过索引来访问数组中的元素。在C语言中,数组的大小在定义时就需要确定,并且数组的下标从0开始。 4. 请介绍一下C语言中的指针。 指针是一个变量,其值为另一个变量的地址。通过指针可以直接访问和修改内存中的数据。使用指针可以提高程序的效率和灵活性。 5. 请介绍一下C语言中的函数。 函数是一段完成特定任务的代码块,可以通过函数名来调用执行。函数可以接收参数并返回一个值,也可以不接收参数或不返回值。 6. 请介绍一下C语言中的流程控制语句。 C语言中的流程控制语句包括条件语句(if-else语句、switch语句)、循环语句(for循环、while循环、do-while循环)和跳转语句(break语句、continue语句、goto语句)。 7. 请介绍一下C语言中的结构体。 结构体是一种自定义的数据类型,可以包含多个不同类型的成员变量。通过结构体可以将多个相关的数据组织在一起。 8. 请介绍一下C语言中的文件操作。 C语言中的文件操作主要包括打开文件、读写文件和关闭文件。可以使用标准库函数来进行文件操作,如fopen、fread、fwrite、fclose等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喵宁一

点赞是最好的赞赏~

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

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

打赏作者

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

抵扣说明:

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

余额充值