百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

LeetCode大厂SQL面试题解(一) sql面试问题大全及答案大全

liebian365 2024-10-28 17:16 22 浏览 0 评论

大家好,我是宁一。


最近会在群里每天更新SQL题目。


又间接督促我勤奋了许多——


题目一:


182. 查找重复的电子邮箱(简单)


编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。


示例:


+----+---------+
| Id | Emai    |
+----+---------+
|1 |  a@b.com |
| 2 | c@d.com  |
|3 | a@b.com  |
+----+---------+


根据以上输入,你的查询应返回以下结果:


+---------+
| Email   |
+---------+
| a@b.com |
+---------+


解题思路:


可以先用子查询,用 count 聚合函数结合 group by 查询出每个邮箱的个数。再用母查询,来判断邮箱个数大于1的记录,就是我们最终想要得到的结果。


第一步:
用子查询查出每个邮箱的个数。


SELECT Email FROM(
  SELECT Email, COUNT(Email) AS num
  FROM Person
  GROUP BY Email




第二步:
根据第一步得到的结果,我们来判断邮箱个数num大于1的记录。

SELECT Email FROM(
  SELECT Email, COUNT(Email) AS num
  FROM Person
  GROUP BY Email
) AS a
WHERE num > 1;





想要自己电脑本地测试,可以用这个快速创建数据库语句:

-- 创建数据库
CREATE database SQLCode;
-- 选择数据库
USE SQLCode;


-- 创建科目表Person 
CREATE TABLE Person(
Id INT,
Email VARCHAR(10));
-- 插入语句
INSERT INTO Person VALUES
(1,'a@b.com'),
(2,'c@d.com'),
(3,'a@b.com');


题目二:

176. 第二高的薪水(简单)


编写一个 SQL 查询,获取并返回 Employee 表中第二高的薪水 。如果不存在第二高的薪水,查询应该返回 null 。


示例 1:


输入:Employee 表


+----+--------+
| id | salary |
+----+--------+
|  1 | 100    |
|  2 | 200    |
|  3 | 300    |
+----+--------+


输出:


+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+


示例 2:


输入:Employee 表:


+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
+----+--------+


输出:


+---------------------+
| SecondHighestSalary |
+---------------------+
| null                |
+---------------------+


解题思路:


将不同的薪资按降序排序,然后使用 LIMIT OFFSET 获得第二高的薪资。

但是如果表中 salary 不同的数据小于2条的时候,则会出现空的情况,因此加一个 IFNULL 进行判断。


知识点:

(1)LIMIT子句基本用法:


用来限制返回记录的数量。


可以通过LIMIT m,n 跳过结果集中的前m条记录,取n条记录。这句话有点绕,我们举个例子。


取第7~9条记录,也就是跳过前6条,从第7条开始取,取7、8、9这3条记录。那应该用LIMIT 6,3来实现。


(2)IFNULL语句基本语法:


IFNULL(值1,值2)


如果值1为NULL,返回值2;如果值1不为NULL,返回值1。


第一步:

将工资倒序排序,并用DISTINCT去重,使用LIMIT 1,1获取第二高的工资。


SELECT DISTINCT Salary
FROM Employee
ORDER by Salary DESC
LIMIT 1,1 # 获取第二高的salary


第二步:

如果没有第二高的工资,返回null,使用IFNULL来实现。


SELECT IFNULL(
    (
        SELECT DISTINCT Salary
        FROM Employee
        ORDER by Salary DESC
        LIMIT 1,1 # 获取第二高的salary
    ),
    NULL # 如果没有,则为 NULL
)


想要自己电脑本地测试,可以用这个快速创建数据表语句:


-- 创建员工表Employee 
CREATE TABLE Employee(
Id INT,
salary INT);
-- 插入语句
INSERT INTO Employee VALUES
(1,100),
(2,200),
(3,300);



题目三:

180. 连续出现的数字(中等)


表:Logs


+-------------+---------+
| Column Name | Type    |
+-------------+---------+
|  id         | int     |
| num         | varchar |
+-------------+---------+


id 是这个表的主键。


编写一个 SQL 查询,查找所有至少连续出现三次的数字。

返回的结果表中的数据可以按 任意顺序 排列。


示例 1:


输入:Logs 表


+----+-----+
| Id | Num |
+----+-----+
| 1  | 1   |
| 2  | 1   |
| 3  | 1   |
| 4  | 3   |
| 5  | 2   |
| 6  | 2   |
| 7  | 2   |
+----+-----+


输出:


+-----------------+
| ConsecutiveNums |
+-----------------+
| 1               |
| 2               |
+-----------------+


解题思路:


通过id+1的方式查找下一次出现的数字,通过id+2的方式查找下下次出现的数字,主要下次和下下次出现的数字和当前的数字相同,就满足了出现至少3次的条件。


知识点:JOIN连接


多张数据表联合查询,需要用到JOIN连接,JOIN连接分为好几种,我们这道题用到了内连接。


INNER JOIN:内连接,也可以只写JOIN。只有进行连接的两个表中,都存在与连接标准相匹配的数据才会被保留下来,相当于两个表的交集。如果前后连接同一张表,也叫自连接。


第一步:

将下次出现的数字和下下次出现的数字,放在同一个表中,方便我们第二步进行比较。


SELECT *
FROM Logs t1
JOIN Logs t2
ON t1.id+1=t2.id
JOIN Logs t3
ON t1.id+2=t3.id




第二步:

加上筛选条件,t1表中的数字,等于t2表中的数字也等于t3表中的数字。


SELECT *
FROM Logs t1
JOIN Logs t2
ON t1.id+1=t2.id
JOIN Logs t3
ON t1.id+2=t3.id
WHERE t1.Num=t2. Num
    AND t1.Num=t3.Num;



第三步:

修改SELECT后面的字段,只将NUM输出就可以了。


SELECT DISTINCT t1.Num
FROM Logs t1
JOIN Logs t2
ON t1.id+1=t2.id
JOIN Logs t3
ON t1.id+2=t3.id
WHERE t1.Num=t2. Num
    AND t1.Num=t3.Num;



想要自己电脑本地测试,可以用这个快速创建数据表语句:

-- 创建表
CREATE TABLE Logs(
Id INT,
Num INT);
-- 插入语句
INSERT INTO Logs VALUES
(1,1),
(2,1),
(3,1),
(4,3),
(5,2),
(6,2),
(7,2);


题目四:

1454. 活跃用户(中等)


现在有Accounts表:该表包含账户 id 和账户的用户名 name。

Logins表:包含登录用户的账户 id 和登录日期 login_date。(用户也许一天内登录多次)


写一个 SQL 查询, 找到活跃用户的 id 和 name,活跃用户是指那些至少连续 3 天登录账户的用户。返回的结果表按照 id 排序。


结果表格式如下例所示:


Accounts 表:


+----+----------+
| id | name     |
+----+----------+
| 1  | '小王'    |
| 7  | ‘小李'    |
+----+----------+


Logins 表:


+----+------------+
| id | login_date |
+----+------------+
| 7  | 2020-05-30 |
| 1  | 2020-05-30 |
| 7  | 2020-05-31 |
| 7  | 2020-06-01 |
| 7  | 2020-06-03 |
| 1  | 2020-06-07 |
+----+------------+


id = 1 的用户小王仅仅登录了 2 次, 所以小王不是活跃用户。

id = 7 的用户小李是连续3天登录的, 所以小李是活跃用户.


解题思路:


这个也是连续的问题,跟上面找连续数字的思路是一个样子,用自连接先将Accounts表和Logins表连接。


再连接一次Logins表,将别名命名为L2,只连接L1表中,每个id相同且相差2天之内的日期。这样与L1表中所有相差两天的日期都会显示出来。


比如:L1表中是5月30号,L2表中最多会查出5月30号、5月31号、6月1号的日期。如果的对应了3个日期,说明用户连续3天都登录了。如果对应了2个日期,说明用户在3天内只登录了两天。


知识点:


DATEDIFF 计算两个日期间隔天数:


SELECT
  DATEDIFF('2022-04-11','2021-04-11') AS "间隔天数",
  DATEDIFF('2022-04-11 01:00','2022-04-10 23:00') AS "间隔天数"





第一步:

先将表格连接起来,并找出L1、L2表中每个id相同,且相差2天之内的日期。


SELECT A.*,L1.login_date,L2.login_date
FROM Accounts A
JOIN logins L1 ON A.id = L1.id
JOIN Logins L2 ON L1.id=L2.id
    AND DATEDIFF(L2.login_date,L1.login_date) BETWEEN 0 AND 2



第二步:

将上方查出的结果分组,看看L1表中相同的日期,对应到L2表中日期的个数。


SELECT A.*,L1.login_date
FROM Accounts A
JOIN logins L1 ON A.id = L1.id
JOIN Logins L2 ON L1.id=L2.id
    AND DATEDIFF(L2.login_date,L1.login_date) BETWEEN 0 AND 2
GROUP BY A.id,A.name,L1.login_date



第三步:

上方表中个数为3的记录,对应的account账户名,就是我们要找的。再将SELECT后面的字段去掉,只剩下Account账户的字段就可以了。

SELECT A.*
FROM Accounts A
JOIN logins L1 ON A.id = L1.id
JOIN Logins L2 ON L1.id=L2.id
    AND DATEDIFF(L2.login_date,L1.login_date) BETWEEN 0 AND 2
GROUP BY A.id,A.name,L1.login_date
HAVING COUNT(DISTINCT L2.login_date)=3



想要自己电脑本地测试,可以用这个快速创建数据表语句:

-- 创建表
CREATE TABLE Accounts(
Id INT,
name VARCHAR(10));
-- 插入语句
INSERT INTO Accounts VALUES
(1,'小王' ),
(7, '小李');
-- 创建表
CREATE TABLE Logins(
Id INT,
login_date DATETIME);
-- 插入语句
INSERT INTO Logins VALUES
(7,'2020-05-30' ),
(1,'2020-05-30' ),
(7,'2020-05-31' ),
(7,'2020-06-01' ),
(7,'2020-06-03' ),
(1,'2020-06-07' );


点击关注,编程入门不迷路~

相关推荐

C#委托—马工教你轻松玩转委托(c#中委托)

前言大家好,我是马工!在C#中有一个小白谈之色变的知识点叫委托,很多学了一两年C#的还不知道委托究竟是什么东西,本文就来帮你彻底解开解惑,从此委托就是小儿科!...

AR农业种植指导(农业种植模式)

以下是一些常见的AR/VR在农业中的应用场景及相关源码示例的一些思路(注意,完整且复杂的源码通常需要根据具体需求和大量开发工作来完成,这里只是简单示例):1.AR农业种植指导-功能描述:通过AR...

C#中timer中的enable和start以及stop的作用分别是什么?

文章来自AI问答的摘录。在C#中,System.Timers.Timer和System.Windows.Forms.Timer都提供了Enabled属性以及Start()和Stop()方法来控制定时器...

AOP实现原理浅析(简述aop的原理以及作用)

在C#中实现一个简单的动态代理框架,可以通过反射和System.Reflection.Emit命名空间动态生成代理类。以下是一个分步指南和示例代码:...

如何防止数据库服务器的 SQL 注入攻击

如何防止数据库服务器的SQL注入攻击防止SQL注入攻击需要从代码开发、数据库配置到安全运维的全流程防护。以下是详细且可操作的防护策略和步骤:...

.NET依赖注入实战:基于Autofac的完全指南与代码示例

...

AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类

...

C# winform中chart控件解决显示大量曲线数据卡顿

前言:...

Java静态三剑客(静态内部类/静态方法/静态类)的正确打开方式

作为Java程序员必知的"静态三剑客",它们看似简单却暗藏玄机!本文将带你解锁高阶玩法,避免99%开发者都会踩的坑!一、概念速览(颠覆传统认知)...

生成AutoCAD图纸批量合并代码(autocad怎么合并图纸)

想要生成AutoCAD图纸批量合并的代码。首先,我需要确定他使用哪个版本的AutoCAD,因为不同版本的API可能不同,比如VBA、.NET(C#或VB.NET)或者AutoLISP。不过用户没有具体...

C#从入门到精通(4)—Linq实现集合快速转换、筛选、排序、分组

前言大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在C#开发中需要经常对集合中的数据进行处理,比如我需要将一个Int类型的集合数...

CSnakes:在.NET项目中嵌入Python代码的工具

...

CSharp(dotNet)绝版面试题,面试大全(二)

21.简述C#的密封类和密封方法?C#中,密封类和密封方法都是使用sealed修饰。密封类表示这个类不能被继承。密封方法表示这个方法不能被重写,和virtual方法相对。22.请介绍C#静态构造器的特...

C#从入门到精通(7)—C#裁剪图像的几种方法总结

前言大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在上位机软件开发过程中经常需要裁剪图像,本文就是对c#中常见的裁剪图像方法进行...

Csharp 进度条的使用(c#进度条是哪个控件)

【开发过程】(1)创建一个Windows应用程序,项目名称为Ex047,窗体默认为Form"(2)在窗体中添加菜单、工具栏和状态栏。(3)面添加ProgressBar.设置。(4)在窗体载入Loa...

取消回复欢迎 发表评论: