面試常見問題——數據庫(二)
目錄:
- 應用實例
- 交換工資【LeetCode】
- 部門工資前三高的所有員工【LeetCode】
- 體育館的人流量【LeetCode】
- 行程和用戶【LeetCode】
- 換座位【LeetCode】
- 連續出現的數字【LeetCode】
- 部門工資最高的員工【LeetCode】
- 刪除重複的電子郵箱【LeetCode】
- 超過五名學生的課【LeetCode】
- 上升的溫度【LeetCode】
- 重新格式化部門表【LeetCode】
- 有趣的電影【LeetCode】
- 從不訂購的客戶【LeetCode】
- 大的國家【LeetCode】
- 超過經理收入的員工【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;