面试常见问题——数据库(二)

面试常见问题——数据库(二)

目录:

  1. 应用实例
    1. 交换工资【LeetCode】
    2. 部门工资前三高的所有员工【LeetCode】
    3. 体育馆的人流量【LeetCode】
    4. 行程和用户【LeetCode】
    5. 换座位【LeetCode】
    6. 连续出现的数字【LeetCode】
    7. 部门工资最高的员工【LeetCode】
    8. 删除重复的电子邮箱【LeetCode】
    9. 超过五名学生的课【LeetCode】
    10. 上升的温度【LeetCode】
    11. 重新格式化部门表【LeetCode】
    12. 有趣的电影【LeetCode】
    13. 从不订购的客户【LeetCode】
    14. 大的国家【LeetCode】
    15. 超过经理收入的员工【LeetCode】

一、应用实例:

1、题目描述:给定一个salary表,如下所示,有 m = 男性 和 f = 女性 的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求只使用一个更新(Update)语句,并且没有中间的临时表。注意,您必只能写一个 Update 语句,请不要编写任何 Select 语句。【LeetCode】
例如:

运行你所编写的更新语句之后,将会得到以下表:

UPDATE salary
SET sex = (
    CASE sex WHEN 'm' THEN 'f'
    WHEN 'f' THEN 'm'
    END
)

2、题目描述:部门工资前三高的所有员工。【LeetCode】
Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentId 。

Department 表包含公司所有部门的信息。

编写一个SQL 查询,找出每个部门获得前三高工资的所有员工。例如,根据上述给定的表,查询结果应返回:

解释:IT 部门中,Max 获得了最高的工资,Randy 和 Joe 都拿到了第二高的工资,Will 的工资排第三。销售部门(Sales)只有两名员工,Henry 的工资最高,Sam 的工资排第二。

CREATE TABLE Department(
	Id INT PRIMARY KEY IDENTITY(1,1),
	Name VARCHAR(50) NOT NULL
);

CREATE TABLE Employee(
	Id INT PRIMARY KEY IDENTITY(1,1),
	Name VARCHAR(50) not null,
	Salary DECIMAL(6,1) not null,
	DepartmentId INT,
	FOREIGN KEY(DepartmentId) REFERENCES Department(Id)
);

INSERT INTO Department(Name)
VALUES('IT'),('Sales');

INSERT INTO Employee(Name, Salary, DepartmentId)
VALUES('Joe', 85000, 1),
('Henry', 80000, 2),
('Sam', 60000, 2),
('Max', 90000, 1),
('Janet', 69000, 1),
('Randy', 85000, 1),
('Will', 70000, 1);

SELECT b.Name AS Department, a.Name AS Employee, Salary
FROM Employee AS a
INNER JOIN Department AS b
ON b.Id = a.DepartmentId
WHERE a.Id in(
	SELECT e1.Id
	FROM Employee e1
	left join Employee e2
	ON e1.DepartmentId = e2.DepartmentId
	AND e1.Salary < e2.Salary
	GROUP BY(e1.Id)
	HAVING COUNT(distinct e2.Salary) <= 2
)
ORDER BY b.Id ASC,  Salary DESC;

3、题目描述:体育馆的人流量。X 市建了一个新的体育馆,每日人流量信息被记录在这三列信息中:序号 (id)、日期 (visit_date)、人流量 (people)。请编写一个查询语句,找出人流量的高峰期。高峰期时,至少连续三行记录中的人流量不少于100。【LeetCode】
例如,表 stadium:

对于上面的示例数据,输出为:

提示:每天只有一行记录,日期随着 id 的增加而增加。

CREATE TABLE stadium(
	id INT PRIMARY KEY IDENTITY(1, 1),
	visit_date DATE NOT NULL,
	people INT NOT NULL
);

INSERT INTO stadium(visit_date, people)
values('2017-01-01', 10),
('2017-01-02', 109),
('2017-01-03', 150),
('2017-01-04', 99),
('2017-01-05', 145),
('2017-01-06', 1455),
('2017-01-07', 199),
('2017-01-08', 188);

//方法一:
SELECT *
FROM (
	SELECT s1.*
	FROM stadium s1
	INNER JOIN stadium s2
	ON s2.id = s1.id + 1
	INNER JOIN stadium s3
	ON s3.id = s2.id + 1
	WHERE (s1.people >= 100 AND s2.people >= 100 AND s3.people >= 100)
	UNION
	SELECT s2.*
	FROM stadium s1
	INNER JOIN stadium s2
	ON s2.id = s1.id + 1
	INNER JOIN stadium s3
	ON s3.id = s2.id + 1
	WHERE (s1.people >= 100 AND s2.people >= 100 AND s3.people >= 100)
	UNION
	SELECT s3.*
	FROM stadium s1
	INNER JOIN stadium s2
	ON s2.id = s1.id + 1
	INNER JOIN stadium s3
	ON s3.id = s2.id + 1
	WHERE (s1.people >= 100 AND s2.people >= 100 AND s3.people >= 100)
)t;

//方法2:
SELECT distinct s1.*
FROM stadium s1, stadium s2, stadium s3
WHERE (
	(s1.id + 1 = s2.id AND s2.id + 1 = s3.id)
	OR (s1.id - 1 = s2.id AND s1.id + 1 = s3.id)
	OR (s1.id - 1 = s2.id AND s2.id - 1 = s3.id)
)AND s1.people >= 100 
AND s2.people >= 100 
AND s3.people >= 100
ORDER BY s1.id;

4、题目描述:行程和用户。【LeetCode】
Trips表中存所有出租车的行程信息。每段行程有唯一键 Id,Client_Id 和 Driver_Id 是Users表中Users_Id 的外键。Status是枚举类型,枚举成员为 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。

Users表存所有用户。每个用户有唯一键 Users_Id。Banned表示这个用户是否被禁止,Role则是一个表示(‘client’, ‘driver’, ‘partner’)的枚举类型。

写一段 SQL 语句查出2013年10月1日至2013年10月3日期间非禁止用户的取消率。基于上表,你的SQL语句应返回如下结果,取消率(Cancellation Rate)保留两位小数。取消率的计算方式如下:(被司机或乘客取消的非禁止用户生成的订单数量) / (非禁止用户生成的订单总数)

CREATE TABLE Users(
	Users_Id INT PRIMARY KEY,
	Banned VARCHAR(10) NOT NULL,
	Role VARCHAR(20) NOT NULL
);

CREATE TABLE Trips(
	Id INT PRIMARY KEY IDENTITY(1, 1),
	Client_Id INT NOT NULL,
	Driver_Id INT NOT NULL,
	City_Id INT NOT NULL,
	Status VARCHAR(50) NOT NULL,
	Request_at DATE NOT NULL
	FOREIGN KEY(Client_Id) REFERENCES Users(Users_id),
	FOREIGN KEY(Driver_Id) REFERENCES Users(Users_id)
);
/*ROUND第一个参数是我们要被操作的数据,第二个参数是设置四舍五入之后小数点后显示几位。*/
SELECT Request_at AS Day, 
ROUND(CAST(SUM(CASE WHEN Status = 'completed' THEN 0 ELSE 1 END) AS FLOAT)/COUNT(Status), 2) AS 'Cancellation Rate'
FROM Trips
LEFT JOIN Users u1
ON u1.Users_Id = Client_Id
LEFT JOIN Users u2
ON u2.Users_Id = Driver_Id
WHERE u1.Banned = 'No'
AND u2.Banned = 'No'
AND Request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY Request_at

SELECT Request_at AS Day, 
ROUND(CAST(SUM(CASE WHEN Status = 'completed' THEN 0 ELSE 1 END) AS FLOAT)/COUNT(Status), 2) AS 'Cancellation Rate'
FROM Trips, Users u1, Users u2
WHERE u1.Users_Id = Client_Id
AND u2.Users_Id = Driver_Id
AND u1.Banned = 'No'
AND u2.Banned = 'No'
AND Request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY Request_at

5、题目描述:小美是一所中学的信息科技老师,她有一张 seat座位表,平时用来储存学生名字和与他们相对应的座位 id。其中纵列的id是连续递增的,小美想改变相邻俩学生的座位。请帮她写一个 SQL query来输出小美想要的结果【LeetCode】
示例:

假如数据输入的是上表,则输出结果如下:

注意:如果学生人数是奇数,则不需要改变最后一个同学的座位。

SELECT s1.id, CASE WHEN s2.student IS NULL THEN s1.student ELSE s2.student END AS student
FROM seat s1
LEFT JOIN seat s2
ON s1.id = CASE WHEN s1.id % 2 != 0 THEN s2.id - 1
ELSE s2.id + 1 END;

6、题目描述:编写一个 SQL 查询,查找所有至少连续出现三次的数字。【LeetCode】

例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。

SELECT DISTINCT log1.Num AS ConsecutiveNums
FROM Logs log1
INNER JOIN Logs log2
ON log1.id + 1 = log2.id
INNER JOIN Logs log3
ON log2.id + 1 = log3.id
WHERE log1.Num = log2.Num
AND log2.Num = log3.Num;

7、题目描述:编写一个 SQL 查询,找出每个部门工资最高的员工。【LeetCode】
Employee 表包含所有员工信息,每个员工有其对应的Id, salary 和 department Id。

Department表包含公司所有部门的信息。

例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。

SELECT t2.Name AS Department, t1.Name AS Employee, t1.Salary
FROM Employee t1, Department t2, (
    SELECT d.Id, MAX(e.Salary) AS Salary
    FROM Employee e, Department d
    WHERE e.DepartmentId = d.Id
    GROUP BY d.Id
)t3
WHERE t3.Id = t1.DepartmentId
AND t2.Id = t3.Id
AND t3.Salary = t1.Salary
ORDER BY Department;

8、题目描述:编写一个 SQL 查询,来删除Person表中所有重复的电子邮箱,重复的邮箱里只保留Id最小的那个。【LeetCode】

Id 是这个表的主键。例如,在运行你的查询语句之后,上面的 Person 表应返回以下几行:

DELETE FROM Person
WHERE Id IN( 
	SELECT p1.Id
	FROM Person p1, Person p2
	WHERE p1.Email = p2.Email
	AND p1.Id > p2.Id
)

9、题目描述:有一个courses 表 ,有: student(学生) 和 class (课程)。请列出所有超过或等于5名学生的课。【LeetCode】
例如,表:

应该输出:

Note:
学生在每个课中不应被重复计算。

SELECT class
FROM courses
GROUP BY class
HAVING COUNT(DISTINCT student) >= 5

10、题目描述:给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。【LeetCode】

例如,根据上述给定的 Weather 表格,返回如下 Id:

SELECT w1.Id
FROM Weather w1
LEFT JOIN Weather w2
ON DATEDIFF(d, w1.RecordDate, w2.RecordDate) = -1
WHERE w2.RecordDate IS NOT NULL
AND w1.Temperature > w2.Temperature

11、题目描述:编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应每个月的收入(revenue)列。【LeetCode】
部门表Department,(id, month) 是表的联合主键。这个表格有关于每个部门每月收入的信息。月份(month)可以取下列值 ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]。

查询结果格式如下面的示例所示:Department 表:

查询得到的结果表:

注意,结果表有 13 列 (1个部门 id 列 + 12个月份的收入列)。

SELECT id,
    MIN(CASE WHEN month = 'Jan' THEN revenue ELSE null END) AS Jan_Revenue,
    MIN(CASE WHEN month = 'Feb' THEN revenue ELSE null END) AS Feb_Revenue,
    MIN(CASE WHEN month = 'Mar' THEN revenue ELSE null END) AS Mar_Revenue,
    MIN(CASE WHEN month = 'Apr' THEN revenue ELSE null END) AS Apr_Revenue,
    MIN(CASE WHEN month = 'May' THEN revenue ELSE null END) AS May_Revenue,
    MIN(CASE WHEN month = 'Jun' THEN revenue ELSE null END) AS Jun_Revenue,
    MIN(CASE WHEN month = 'Jul' THEN revenue ELSE null END) AS Jul_Revenue,
    MIN(CASE WHEN month = 'Aug' THEN revenue ELSE null END) AS Aug_Revenue,
    MIN(CASE WHEN month = 'Sep' THEN revenue ELSE null END) AS Sep_Revenue,
    MIN(CASE WHEN month = 'Oct' THEN revenue ELSE null END) AS Oct_Revenue,
    MIN(CASE WHEN month = 'Nov' THEN revenue ELSE null END) AS Nov_Revenue,
    MIN(CASE WHEN month = 'Dec' THEN revenue ELSE null END) AS Dec_Revenue
FROM Department
GROUP BY id;

12、某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。作为该电影院的信息部主管,您需要编写一个 SQL查询,找出所有影片描述为非boring(不无聊)的并且 id 为奇数的影片,结果请按等级 rating 排列。【LeetCode】
例如,下表 cinema:

对于上面的例子,则正确的输出是为:

SELECT id, movie, description, rating
FROM cinema
WHERE id % 2 = 1
AND description != 'boring'
ORDER BY rating DESC;

13、题目描述:某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。【LeetCode】
Customers 表:

Orders 表:

例如给定上述表格,你的查询应返回:

SELECT Name AS Customers
FROM Customers
WHERE Id NOT IN (
    SELECT CustomerId
    FROM Orders
)

14、题目描述:编写一个SQL查询,输出表中所有大国家的名称、人口和面积。【LeetCode】
World 表:

如果一个国家的面积超过300万平方公里,或者人口超过2500万,那么这个国家就是大国家。
例如,根据上表,我们应该输出:

SELECT name, population, area
FROM World
WHERE population >= 25000000
OR area >= 3000000

15、题目描述:给定Employee表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。【LeetCode】
Employee表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。

在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。

SELECT e1.Name AS Employee
FROM Employee e1, Employee e2
WHERE e1.ManagerId = e2.Id
AND e2.Salary < e1.Salary;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章