面試常見問題——數據庫(二)

面試常見問題——數據庫(二)

目錄:

  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;

 

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