Mysql 場景題一 完整版

題目一

小美是一所中學的信息科技老師,她有一張 seat 座位表,平時用來儲存學生名字和與他們相對應的座位 id。

其中縱列的 id 是連續遞增的

小美想改變相鄰倆學生的座位。

你能不能幫她寫一個 SQL query 來輸出小美想要的結果呢?

示例:

±--------±--------+

| id | student |

±--------±--------+

| 1 | Abbot |

| 2 | Doris |

| 3 | Emerson |

| 4 | Green |

| 5 | Jeames |

±--------±--------+

假如數據輸入的是上表,則輸出結果如下:

±--------±--------+

| id | student |

±--------±--------+

| 1 | Doris |

| 2 | Abbot |

| 3 | Green |

| 4 | Emerson |

| 5 | Jeames |

±--------±--------+

注意:

如果學生人數是奇數,則不需要改變最後一個同學的座位。

SELECT if(id%2=1,
        if(id=@a,
        id,
        id+1),
        id-1) id,
        student
FROM seat s,
  (SELECT @a:=count(id)
  FROM seat) ret
ORDER BY  id;

題目二

在 Facebook 或者 Twitter 這樣的社交應用中,人們經常會發好友申請也會收到其他人的好友申請。

表 request_accepted 存儲了所有好友申請通過的數據記錄,其中, requester_id 和 accepter_id 都是用戶的編號。

| requester_id | accepter_id | accept_date|

|--------------|-------------|------------|

| 1 | 2 | 2016_06-03 |

| 1 | 3 | 2016-06-08 |

| 2 | 3 | 2016-06-08 |

| 3 | 4 | 2016-06-09 |

寫一個查詢語句,求出誰擁有最多的好友和他擁有的好友數目。對於上面的樣例數據,結果爲:

| id | num |

|----|-----|

| 3 | 3 |

注意:

保證擁有最多好友數目的只有 1 個人。

好友申請只會被接受一次,所以不會有 requester_id 和 accepter_id 值都相同的重複記錄。

解釋:

編號爲 ‘3’ 的人是編號爲 ‘1’,‘2’ 和 ‘4’ 的好友,所以他總共有 3 個好友,比其他人都多。

進階:

在真實世界裏,可能會有多個人擁有好友數相同且最多,你能找到所有這些人嗎?

SELECT id AS id,
         ucnt AS num
FROM 
  (SELECT id,
         count(1) AS ucnt
  FROM 
    (SELECT requester_id AS id
    FROM request_accepted
    UNION
    allSELECT accepter_id AS id
    FROM request_accepted )
    GROUP BY  id
    ORDER BY  ucnt DESC )
  WHERE rownum = 1

題目三

表 point_2d 保存了所有點(多於 2 個點)的座標 (x,y) ,這些點在平面上兩兩不重合。

寫一個查詢語句找到兩點之間的最近距離,保留 2 位小數。

| x | y |

|----|----|

| -1 | -1 |

| 0 | 0 |

| -1 | -2 |

最近距離在點 (-1,-1) 和(-1,2) 之間,距離爲 1.00 。所以輸出應該爲:

| shortest |

|----------|

| 1.00 |

注意:任意點之間的最遠距離小於 10000 。

SELECT ROUND(MIN(shortest),
        2) shortest FROM
  (SELECT POWER(POWER((p1.x-p2.x),
        2)+POWER((p1.y-p2.y),
        2),
        0.5) shortest
  FROM point_2d p1,point_2d p2
  WHERE p1.x !=p2.x
          OR p1.y != p2.y )a

題目四

編寫一個 SQL 查詢來實現分數排名。如果兩個分數相同,則兩個分數排名(Rank)相同。請注意,平分後的下一個名次應該是下一個連續的整數值。換句話說,名次之間不應該有“間隔”。

±—±------+

| Id | Score |

±—±------+

| 1 | 3.50 |

| 2 | 3.65 |

| 3 | 4.00 |

| 4 | 3.85 |

| 5 | 4.00 |

| 6 | 3.65 |

±—±------+

例如,根據上述給定的 Scores 表,你的查詢應該返回(按分數從高到低排列):

±------±-----+

| Score | Rank |

±------±-----+

| 4.00 | 1 |

| 4.00 | 1 |

| 3.85 | 2 |

| 3.65 | 3 |

| 3.65 | 3 |

| 3.50 | 4 |

±------±-----+

SELECT a.Score,
         sum(case
    WHEN b.Score>=a.Score THEN
    1 end) AS Rank
FROM Scores a, 
  (SELECT DISTINCT Score
  FROM Scores ) b
GROUP BY  a.id
ORDER BY  a.Score desc; 

題目五

給定一個表 tree,id 是樹節點的編號, p_id 是它父節點的 id 。

±—±-----+

| id | p_id |

±—±-----+

| 1 | null |

| 2 | 1 |

| 3 | 1 |

| 4 | 2 |

| 5 | 2 |

±—±-----+

樹中每個節點屬於以下三種類型之一:

葉子:如果這個節點沒有任何孩子節點。

根:如果這個節點是整棵樹的根,即沒有父節點。

內部節點:如果這個節點既不是葉子節點也不是根節點。

寫一個查詢語句,輸出所有節點的編號和節點的類型,並將結果按照節點編號排序。上面樣例的結果爲:

±—±-----+

| id | Type |

±—±-----+

| 1 | Root |

| 2 | Inner|

| 3 | Leaf |

| 4 | Leaf |

| 5 | Leaf |

±—±-----+

解釋

節點 ‘1’ 是根節點,因爲它的父節點是 NULL ,同時它有孩子節點 ‘2’ 和 ‘3’ 。

節點 ‘2’ 是內部節點,因爲它有父節點 ‘1’ ,也有孩子節點 ‘4’ 和 ‘5’ 。

節點 ‘3’, ‘4’ 和 ‘5’ 都是葉子節點,因爲它們都有父節點同時沒有孩子節點。

樣例中樹的形態如下:

1

/ \

2 3

/ \

4 5

SELECT DISTINCT t1.id,
         (CASE
    WHEN t1.p_id IS NULL THEN
    'Root' ELSE
    CASE
    WHEN t2.id IS NULL THEN
    'Leaf'
    ELSE 'Inner'
    END END) AS Type
FROM tree t1
LEFT JOIN tree t2
    ON t1.id=t2.p_id

題目六

Employee 表包含所有員工和他們的經理。每個員工都有一個 Id,並且還有一列是經理的 Id。

±-----±---------±----------±---------+

|Id |Name |Department |ManagerId |

±-----±---------±----------±---------+

|101 |John |A |null |

|102 |Dan |A |101 |

|103 |James |A |101 |

|104 |Amy |A |101 |

|105 |Anne |A |101 |

|106 |Ron |B |101 |

±-----±---------±----------±---------+

給定 Employee 表,請編寫一個SQL查詢來查找至少有5名直接下屬的經理。對於上表,您的SQL查詢應該返回:

±------+

| Name |

±------+

| John |

±------+

SELECT b.Name
FROM employee a
INNER JOIN employee b
    ON a.managerid= b.id
GROUP BY  a.managerid
HAVING count(*)>=5; 

題目七

一所大學有 2 個數據表,分別是 student 和 department ,這兩個表保存着每個專業的學生數據和院系數據。

寫一個查詢語句,查詢 department 表中每個專業的學生人數 (即使沒有學生的專業也需列出)。

將你的查詢結果按照學生人數降序排列。 如果有兩個或兩個以上專業有相同的學生數目,將這些部門按照部門名字的字典序從小到大排列。

student 表格如下:

| Column Name | Type |

|--------------|-----------|

| student_id | Integer |

| student_name | String |

| gender | Character |

| dept_id | Integer |

其中, student_id 是學生的學號, student_name 是學生的姓名, gender 是學生的性別, dept_id 是學生所屬專業的專業編號。

department 表格如下:

| Column Name | Type |

|-------------|---------|

| dept_id | Integer |

| dept_name | String |

dept_id 是專業編號, dept_name 是專業名字。

這裏是一個示例輸入:

student 表格:

| student_id | student_name | gender | dept_id |

|------------|--------------|--------|---------|

| 1 | Jack | M | 1 |

| 2 | Jane | F | 1 |

| 3 | Mark | M | 2 |

department 表格:

| dept_id | dept_name |

|---------|-------------|

| 1 | Engineering |

| 2 | Science |

| 3 | Law |

示例輸出爲:

| dept_name | student_number |

|-------------|----------------|

| Engineering | 2 |

| Science | 1 |

| Law | 0 |

SELECT dept_name,
        (case
    WHEN student_num is NULL THEN
    0
    ELSE student_num end) student_number
FROM 
  (SELECT dept_id,
        count(*) student_num
  FROM student
  GROUP BY  dept_id) t1
RIGHT JOIN department t2
    ON t1.dept_id=t2.dept_id
ORDER BY  student_number desc,dept_name asc

題目八

寫一個查詢語句,將 2016 年 (TIV_2016) 所有成功投資的金額加起來,保留 2 位小數。

對於一個投保人,他在 2016 年成功投資的條件是:

他在 2015 年的投保額 (TIV_2015) 至少跟一個其他投保人在 2015 年的投保額相同。

他所在的城市必須與其他投保人都不同(也就是說維度和經度不能跟其他任何一個投保人完全相同)。

輸入格式:

表 insurance 格式如下:

| Column Name | Type |

|-------------|---------------|

| PID | INTEGER(11) |

| TIV_2015 | NUMERIC(15,2) |

| TIV_2016 | NUMERIC(15,2) |

| LAT | NUMERIC(5,2) |

| LON | NUMERIC(5,2) |

PID 字段是投保人的投保編號, TIV_2015 是該投保人在2015年的總投保金額, TIV_2016 是該投保人在2016年的投保金額, LAT 是投保人所在城市的維度, LON 是投保人所在城市的經度。

樣例輸入

| PID | TIV_2015 | TIV_2016 | LAT | LON |

|-----|----------|----------|-----|-----|

| 1 | 10 | 5 | 10 | 10 |

| 2 | 20 | 20 | 20 | 20 |

| 3 | 10 | 30 | 20 | 20 |

| 4 | 10 | 40 | 40 | 40 |

樣例輸出

| TIV_2016 |

|----------|

| 45.00 |

解釋

就如最後一個投保人,第一個投保人同時滿足兩個條件:

1. 他在 2015 年的投保金額 TIV_2015 爲 ‘10’ ,與第三個和第四個投保人在 2015 年的投保金額相同。

2. 他所在城市的經緯度是獨一無二的。

第二個投保人兩個條件都不滿足。他在 2015 年的投資 TIV_2015 與其他任何投保人都不相同。

且他所在城市的經緯度與第三個投保人相同。基於同樣的原因,第三個投保人投資失敗。

所以返回的結果是第一個投保人和最後一個投保人的 TIV_2016 之和,結果是 45 。

SELECT sum(case
    WHEN t3.TIV_2015 is NOT NULL THEN
    t2.TIV_2016
    ELSE 0 end) TIV_2016 from
  (SELECT TIV_2015
  FROM insurance
  GROUP BY  TIV_2015
  HAVING count(TIV_2015)>1)t3
RIGHT JOIN 
  (SELECT *
  FROM insurance
  GROUP BY  LAT, LON
  HAVING count(LAT) = 1
          AND count(LON) = 1) t2
    ON t2.TIV_2015=t3.TIV_2015

題目九

Customer 表:

±------------±--------+

| Column Name | Type |

±------------±--------+

| customer_id | int |

| product_key | int |

±------------±--------+

product_key 是 Product 表的外鍵。

Product 表:

±------------±--------+

| Column Name | Type |

±------------±--------+

| product_key | int |

±------------±--------+

product_key 是這張表的主鍵。

寫一條 SQL 查詢語句,從 Customer 表中查詢購買了 Product 表中所有產品的客戶的 id。

示例:

Customer 表:

±------------±------------+

| customer_id | product_key |

±------------±------------+

| 1 | 5 |

| 2 | 6 |

| 3 | 5 |

| 3 | 6 |

| 1 | 6 |

±------------±------------+

Product 表:

±------------+

| product_key |

±------------+

| 5 |

| 6 |

±------------+

Result 表:

±------------+

| customer_id |

±------------+

| 1 |

| 3 |

±------------+

購買了所有產品(5 和 6)的客戶的 id 是 1 和 3 。

SELECT customer_id
FROM 
  (SELECT DISTINCT c.customer_id,
         c.product_key AS cpk,
         p.product_key AS ppk
  FROM customer c
  LEFT JOIN product p
      ON c.product_key=p.product_key) tmp
GROUP BY  customer_id
HAVING COUNT(cpk) = 
  (SELECT COUNT(product_key)
  FROM product)
        AND COUNT(ppk) = 
  (SELECT COUNT(product_key)
  FROM product) 

題目十

編寫一個 SQL 查詢,查找所有至少連續出現三次的數字。

±—±----+

| Id | Num |

±—±----+

| 1 | 1 |

| 2 | 1 |

| 3 | 1 |

| 4 | 2 |

| 5 | 1 |

| 6 | 2 |

| 7 | 2 |

±—±----+

例如,給定上面的 Logs 表, 1 是唯一連續出現至少三次的數字。

±----------------+

| ConsecutiveNums |

±----------------+

| 1 |

±----------------+

SELECT DISTINCT l1.Num AS ConsecutiveNums
FROM Logs l1, Logs l2, Logs l3
WHERE l1.Id = l2.Id - 1
        AND l2.Id = l3.Id - 1
        AND l1.Num = l2.Num
        AND l2.Num = l3.Num ;

題目十一

表: Candidate

±----±--------+

| id | Name |

±----±--------+

| 1 | A |

| 2 | B |

| 3 | C |

| 4 | D |

| 5 | E |

±----±--------+

表: Vote

±----±-------------+

| id | CandidateId |

±----±-------------+

| 1 | 2 |

| 2 | 4 |

| 3 | 3 |

| 4 | 2 |

| 5 | 5 |

±----±-------------+

id 是自動遞增的主鍵,

CandidateId 是 Candidate 表中的 id.

請編寫 sql 語句來找到當選者的名字,上面的例子將返回當選者 B.

±-----+

| Name |

±-----+

| B |

±-----+

注意:

你可以假設沒有平局,換言之,最多隻有一位當選者。

elect t3.name Name
FROM Candidate t3, 
  (SELECT t1.CandidateId CandidateId
  FROM Vote t1
  GROUP BY  t1.CandidateId
  ORDER BY  count(*) DESC limit 1)t2
WHERE t3.id=t2.CandidateId 

題目十二

Employee 表包含所有員工信息,每個員工有其對應的 Id, salary 和 department Id。

±—±------±-------±-------------+

| Id | Name | Salary | DepartmentId |

±—±------±-------±-------------+

| 1 | Joe | 70000 | 1 |

| 2 | Henry | 80000 | 2 |

| 3 | Sam | 60000 | 2 |

| 4 | Max | 90000 | 1 |

±—±------±-------±-------------+

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

±—±---------+

| Id | Name |

±—±---------+

| 1 | IT |

| 2 | Sales |

±—±---------+

編寫一個 SQL 查詢,找出每個部門工資最高的員工。例如,根據上述給定的表格,Max 在 IT 部門有最高工資,Henry 在 Sales 部門有最高工資。

±-----------±---------±-------+

| Department | Employee | Salary |

±-----------±---------±-------+

| IT | Max | 90000 |

| Sales | Henry | 80000 |

±-----------±---------±-------+

SELECT Department.name AS 'Department', Employee.name AS 'Employee', Salary
FROM Employee
JOIN Department
    ON Employee.DepartmentId = Department.Id
WHERE (Employee.DepartmentId , Salary) IN 
  (SELECT DepartmentId,
         MAX(Salary)
  FROM Employee
  GROUP BY  DepartmentId ) ; 

題目十三

從 survey_log 表中獲得回答率最高的問題,survey_log 表包含這些列:uid, action, question_id, answer_id, q_num, timestamp。

uid 表示用戶 id;action 有以下幾種值:“show”,“answer”,“skip”;當 action 值爲 “answer” 時 answer_id 非空,而 action 值爲 “show” 或者 “skip” 時 answer_id 爲空;q_num 表示當前會話中問題的編號。

請編寫SQL查詢來找到具有最高回答率的問題。

示例:

輸入:

±-----±----------±-------------±-----------±----------±-----------+

| uid | action | question_id | answer_id | q_num | timestamp |

±-----±----------±-------------±-----------±----------±-----------+

| 5 | show | 285 | null | 1 | 123 |

| 5 | answer | 285 | 124124 | 1 | 124 |

| 5 | show | 369 | null | 2 | 125 |

| 5 | skip | 369 | null | 2 | 126 |

±-----±----------±-------------±-----------±----------±-----------+

輸出:

±------------+

| survey_log |

±------------+

| 285 |

±------------+

解釋:

問題285的回答率爲 1/1,而問題369回答率爲 0/1,因此輸出285。

注意: 回答率最高的含義是:同一問題編號中回答數佔顯示數的比例。

SELECT question_id AS survey_log
FROM survey_log
GROUP BY  question_id
ORDER BY  ( ifnull( count( answer_id ), 0 ) / count( * ) ) DESC LIMIT 1

題目十四

在 facebook 中,表 follow 會有 2 個字段: followee, follower ,分別表示被關注者和關注者。

請寫一個 sql 查詢語句,對每一個關注者,查詢他的關注者數目。

比方說:

±------------±-----------+

| followee | follower |

±------------±-----------+

| A | B |

| B | C |

| B | D |

| D | E |

±------------±-----------+

應該輸出:

±------------±-----------+

| follower | num |

±------------±-----------+

| B | 2 |

| D | 1 |

±------------±-----------+

解釋:

B 和 D 都在在 follower 字段中出現,作爲被關注者,B 被 C 和 D 關注,D 被 E 關注。A 不在 follower 字段內,所以A不在輸出列表中。

注意:

被關注者永遠不會被他 / 她自己關注。

將結果按照字典序返回。

SELECT f1.follower AS follower,
         count(distinct f2.follower) AS num
FROM follow f1, follow f2
WHERE f1.follower = f2.followee
GROUP BY  f1.follower
ORDER BY  f1.follower
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章