目錄
- 1、空值處理
- 1.1、統計有未完成狀態的試卷的未完成數和未完成率
- 1.2、0 級用戶高難度試卷的平均用時和平均得分
- 2、高級條件語句
- 2.1、篩選限定昵稱成就值活躍日期的用戶(較難)
- 2.2、篩選昵稱規則和試卷規則的作答記錄(較難)
- 2.3、各用戶等級的不同得分表現占比(較難)
- 3、限量查詢
- 3.1、注冊時間最早的三個人
- 3.2、注冊當天就完成了試卷的名單第三頁(較難)
- 4、文本轉換函數
- 4.1、修復串列了的記錄
- 4.2、對過長的昵稱截取處理
1、空值處理
1.1、統計有未完成狀態的試卷的未完成數和未完成率
描述:
現有試卷作答記錄表 exam_record
(uid
用戶 ID, exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間,score
得分),數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:01 | 80 |
2 | 1001 | 9001 | 2021-05-02 10:01:01 | 2021-05-02 10:30:01 | 81 |
3 | 1001 | 9001 | 2021-09-02 12:01:01 | (NULL) | (NULL) |
請統計有未完成狀態的試卷的未完成數 incomplete_cnt
和未完成率 incomplete_rate
。由示例數據結果輸出如下:
exam_id | incomplete_cnt | complete_rate |
---|---|---|
9001 | 1 | 0.333 |
解釋:試卷 9001 有 3 次被作答的記錄,其中兩次完成,1 次未完成,因此未完成數為 1,未完成率為 0.333(保留 3 位小數)
思路:
這題只需要注意一個是有條件限制,一個是沒條件限制的;要么分別查詢條件,然后合并;要么直接在 select 里面進行條件判斷。
答案:
SELECT exam_id,COUNT(submit_time IS NULL OR NULL) incomplete_cnt,ROUND(COUNT(submit_time IS NULL OR NULL)/COUNT(*),3) complete_rate
FROM exam_record
GROUP BY exam_id
HAVING incomplete_cnt <> 0
注意:
COUNT(submit_time IS NULL OR NULL)
:
submit_time IS NULL OR NULL
是一個邏輯表達式。submit_time IS NULL
會返回一個布爾值TRUE
或FALSE
,然后OR NULL
操作將結果轉換為TRUE
或NULL
。由于NULL
在OR
操作中不會影響TRUE
的結果,所以結果等效于submit_time IS NULL
。- 這樣,表達式的結果是
TRUE
或NULL
。 - 然而,
COUNT
函數只會計算非NULL
的值,因此它只會計算TRUE
的次數。實際上,這意味著它會統計submit_time
為NULL
的次數。
COUNT(submit_time IS NULL)
:
submit_time IS NULL
是一個布爾表達式,會返回TRUE
或FALSE
。- 這里
COUNT
函數計算的是真值TRUE
和FALSE
的數量,而不是NULL
的數量。 - 由于
COUNT
只計算非NULL
的值,這意味著submit_time IS NULL
返回的所有TRUE
或FALSE
值都被計數為 1。因此,它統計的是記錄的總數,因為TRUE
和FALSE
都不是NULL
。
總結
-
第一個查詢
COUNT(submit_time IS NULL OR NULL)
實際上統計的是submit_time
列為空的記錄數,因為TRUE
和NULL
中只有TRUE
被計數。 -
第二個查詢
COUNT(submit_time IS NULL)
統計的是所有記錄的總數,因為布爾表達式TRUE
或FALSE
都被認為是非NULL
,因此都被計數。
1.2、0 級用戶高難度試卷的平均用時和平均得分
描述:
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人 1 號 | 10 | 0 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人 2 號 | 2100 | 6 | 算法 | 2020-01-01 10:00:00 |
試卷信息表 examination_info
(exam_id
:試卷 ID, tag
:試卷類別, difficulty
:試卷難度, duration
:考試時長, release_time
:發布時間),示例數據如下:
id | exam_id | tag | difficulty | duration | release_time |
---|---|---|---|---|---|
1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 |
2 | 9002 | SQL | easy | 60 | 2020-01-01 10:00:00 |
3 | 9004 | 算法 | medium | 80 | 2020-01-01 10:00:00 |
試卷作答記錄表 exam_record
(uid
用戶 ID,exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間, score
得分) 示例數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:59 | 80 |
2 | 1001 | 9001 | 2021-05-02 10:01:01 | (NULL) | (NULL) |
3 | 1001 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 |
4 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:32:00 | 20 |
5 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 |
6 | 1001 | 9002 | 2021-09-01 12:01:01 | (NULL) | (NULL) |
7 | 1002 | 9002 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 |
請輸出每個 0 級用戶所有的高難度試卷考試平均用時和平均得分,未完成的默認試卷最大考試時長和 0 分處理。由示例數據結果輸出如下:
uid | avg_score | avg_time_took |
---|---|---|
1001 | 33 | 36.7 |
解釋:0 級用戶有 1001,高難度試卷有 9001,1001 作答 9001 的記錄有 3 條,分別用時 20 分鐘、未完成(試卷時長 60 分鐘)、30 分鐘(未滿 31 分鐘),分別得分為 80 分、未完成(0 分處理)、20 分。因此他的平均用時為 110/3=36.7(保留一位小數),平均得分為 33 分(取整)
思路:這題用IF是判斷的最方便的,因為涉及到 NULL 值的判斷。當然 case when
也可以,大同小異。這題的難點就在于空值的處理,其他的這些查詢條件什么的,我相信難不倒大家。
SELECT uid,ROUND(AVG(new_score)) AS avg_score,ROUND(AVG(time_diff),1) AS avg_time_tookFROM (SELECT er.uid,IF(er.submit_time IS NOT NULL,TIMESTAMPDIFF(MINUTE,start_time,submit_time),ei.duration) AS time_diff,IF(er.submit_time IS NOT NULL,er.score,0) AS new_scoreFROM exam_record erLEFT JOIN user_info ui ON er.uid = ui.uidLEFT JOIN examination_info ei ON er.exam_id = ei.exam_idWHERE ui.`level` = 0 AND ei.difficulty = 'hard'
) t
GROUP BY uid
2、高級條件語句
2.1、篩選限定昵稱成就值活躍日期的用戶(較難)
描述:
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人 1 號 | 1000 | 2 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人 2 號 | 1200 | 3 | 算法 | 2020-01-01 10:00:00 |
3 | 1003 | 高達 3 號 | 2200 | 5 | 算法 | 2020-01-01 10:00:00 |
4 | 1004 | 機器人 4 號 | 2500 | 6 | 算法 | 2020-01-01 10:00:00 |
5 | 1005 | 機器人 5 號 | 3000 | 7 | C++ | 2020-01-01 10:00:00 |
現有試卷作答記錄表 exam_record
(uid
用戶 ID,exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間, score
得分) 示例數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:59 | 80 |
3 | 1001 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 |
2 | 1001 | 9001 | 2021-05-02 10:01:01 | (NULL) | (NULL) |
4 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:32:00 | 20 |
6 | 1001 | 9002 | 2021-09-01 12:01:01 | (NULL) | (NULL) |
5 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 |
11 | 1002 | 9001 | 2020-01-01 12:01:01 | 2020-01-01 12:31:01 | 81 |
12 | 1002 | 9002 | 2020-02-01 12:01:01 | 2020-02-01 12:31:01 | 82 |
13 | 1002 | 9002 | 2020-02-02 12:11:01 | 2020-02-02 12:31:01 | 83 |
7 | 1002 | 9002 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 |
16 | 1002 | 9001 | 2021-09-06 12:01:01 | 2021-09-06 12:21:01 | 80 |
17 | 1002 | 9001 | 2021-09-06 12:01:01 | (NULL) | (NULL) |
18 | 1002 | 9001 | 2021-09-07 12:01:01 | (NULL) | (NULL) |
8 | 1003 | 9003 | 2021-02-06 12:01:01 | (NULL) | (NULL) |
9 | 1003 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 89 |
10 | 1004 | 9002 | 2021-08-06 12:01:01 | (NULL) | (NULL) |
14 | 1005 | 9001 | 2021-02-01 11:01:01 | 2021-02-01 11:31:01 | 84 |
15 | 1006 | 9001 | 2021-02-01 11:01:01 | 2021-02-01 11:31:01 | 84 |
題目練習表 practice_record
(uid
用戶 ID, question_id
題目 ID, submit_time 提交時間, score
得分):
id | uid | question_id | submit_time | score |
---|---|---|---|---|
1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 |
2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 |
3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 |
4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 |
5 | 1003 | 8002 | 2021-09-01 19:38:01 | 80 |
請找到昵稱以『機器人』開頭『號』結尾、成就值在 1200~2500 之間,且最近一次活躍(答題或作答試卷)在 2021 年 9 月的用戶信息。
由示例數據結果輸出如下:
uid | nick_name | achievement |
---|---|---|
1002 | 機器人 2 號 | 1200 |
解釋:昵稱以『機器人』開頭『號』結尾且成就值在 1200~2500 之間的有 1002、1004;
1002 最近一次試卷區活躍為 2021 年 9 月,最近一次題目區活躍為 2021 年 9 月;1004 最近一次試卷區活躍為 2021 年 8 月,題目區未活躍。
因此最終滿足條件的只有 1002。
思路:
先根據條件列出主要查詢語句
昵稱以『機器人』開頭『號』結尾: nick_name LIKE "機器人%號"
成就值在 1200~2500 之間:achievement BETWEEN 1200 AND 2500
第三個條件因為限定了為 9 月,所以直接寫就行:( date_format( record.submit_time, '%Y%m' )= 202109 OR date_format( pr.submit_time, '%Y%m' )= 202109 )
答案:
SELECT DISTINCT u_info.uid,u_info.nick_name,u_info.achievement
FROM user_info u_info
LEFT JOIN exam_record record ON record.uid = u_info.uid
LEFT JOIN practice_record pr ON u_info.uid = pr.uid
WHERE u_info.nick_name LIKE "機器人%號"AND u_info.achievement BETWEEN 1200AND 2500AND (date_format(record.submit_time, '%Y%m')= 202109OR date_format(pr.submit_time, '%Y%m')= 202109)
GROUP BY u_info.uid
2.2、篩選昵稱規則和試卷規則的作答記錄(較難)
描述:
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人1號 | 1900 | 2 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人2號 | 1200 | 3 | 算法 | 2020-01-01 10:00:00 |
3 | 1003 | 機器人3 號 ♂ | 2200 | 5 | 算法 | 2020-01-01 10:00:00 |
4 | 1004 | 機器人 4號 | 2500 | 6 | 算法 | 2020-01-01 10:00:00 |
5 | 1005 | 機器人555號 | 2000 | 7 | C++ | 2020-01-01 10:00:00 |
6 | 1006 | 666666 | 3000 | 6 | C++ | 2020-01-01 10:00:00 |
試卷信息表 examination_info
(exam_id
:試卷 ID, tag
:試卷類別, difficulty
:試卷難度, duration
:考試時長, release_time
:發布時間),示例數據如下:
id | exam_id | tag | difficulty | duration | release_time |
---|---|---|---|---|---|
1 | 9001 | C++ | hard | 60 | 2020-01-01 10:00:00 |
2 | 9002 | c# | hard | 80 | 2020-01-01 10:00:00 |
3 | 9003 | SQL | medium | 70 | 2020-01-01 10:00:00 |
現有試卷作答記錄表 exam_record
(uid
用戶 ID,exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間, score
得分) 示例數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:59 | 80 |
2 | 1001 | 9001 | 2021-05-02 10:01:01 | (NULL) | (NULL) |
4 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:32:00 | 20 |
3 | 1001 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 |
5 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 |
6 | 1001 | 9002 | 2021-09-01 12:01:01 | (NULL) | (NULL) |
11 | 1002 | 9001 | 2020-01-01 12:01:01 | 2020-01-01 12:31:01 | 81 |
16 | 1002 | 9001 | 2021-09-06 12:01:01 | 2021-09-06 12:21:01 | 80 |
17 | 1002 | 9001 | 2021-09-06 12:01:01 | (NULL) | (NULL) |
18 | 1002 | 9001 | 2021-09-07 12:01:01 | (NULL) | (NULL) |
7 | 1002 | 9002 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 |
12 | 1002 | 9002 | 2020-02-01 12:01:01 | 2020-02-01 12:31:01 | 82 |
13 | 1002 | 9002 | 2020-02-02 12:11:01 | 2020-02-02 12:31:01 | 83 |
9 | 1003 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 89 |
8 | 1003 | 9003 | 2021-02-06 12:01:01 | (NULL) | (NULL) |
10 | 1004 | 9002 | 2021-08-06 12:01:01 | (NULL) | (NULL) |
14 | 1005 | 9001 | 2021-02-01 11:01:01 | 2021-02-01 11:31:01 | 84 |
15 | 1006 | 9001 | 2021-02-01 11:01:01 | 2021-09-01 11:31:01 | 84 |
找到昵稱以"機器人"+純數字+"號"或者純數字組成的用戶對于字母 c 開頭的試卷類別(如 C,C++,c#等)的已完成的試卷 ID 和平均得分,按用戶 ID、平均分升序排序。由示例數據結果輸出如下:
uid | exam_id | avg_score |
---|---|---|
1006 | 9001 | 84 |
解釋:昵稱滿足條件的用戶有 1001、1002、1004、1005、1006;
c 開頭的試卷有 9001、9002;
滿足上述條件的作答記錄中,1002 完成 9001 的得分有 81、80,平均分為 81(80.5 取整四舍五入得 81);
1002 完成 9002 的得分有 90、82、83,平均分為 85;
思路:
還是老樣子,既然給出了條件,就先把各個條件先寫出來
找到昵稱以"機器人"+純數字+"號"或者純數字組成的用戶: 我最開始是這么寫的:nick_name LIKE '機器人%號' OR nick_name REGEXP'^[0-9]+$'
,如果表中有個 “機器人 H 號” ,那也能通過。
所以這里還得用正則: nick_name LIKE '^機器人[0-9]+號'
對于字母 c 開頭的試卷類別: e_info.tag LIKE 'c%'
或者 tag regexp '^c|^C'
第一個也能匹配到大寫 C
答案:
SELECT UID,exam_id,ROUND(AVG(score), 0) avg_score
FROM exam_record
WHERE UID IN(SELECT UIDFROM user_infoWHERE nick_name RLIKE "^機器人[0-9]+號 $"OR nick_name RLIKE "^[0-9]+$")AND exam_id IN(SELECT exam_idFROM examination_infoWHERE tag RLIKE "^[cC]")AND score IS NOT NULL
GROUP BY UID,exam_id
ORDER BY UID,avg_score;
2.3、各用戶等級的不同得分表現占比(較難)
描述:
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人1號 | 19 | 0 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人2號 | 1200 | 3 | 算法 | 2020-01-01 10:00:00 |
3 | 1003 | 機器人3 號 ♂ | 22 | 0 | 算法 | 2020-01-01 10:00:00 |
4 | 1004 | 機器人 4號 | 25 | 0 | 算法 | 2020-01-01 10:00:00 |
5 | 1005 | 機器人555號 | 2000 | 7 | C++ | 2020-01-01 10:00:00 |
6 | 1006 | 666666 | 3000 | 6 | C++ | 2020-01-01 10:00:00 |
現有試卷作答記錄表 exam_record
(uid
用戶 ID,exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間, score
得分) 示例數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:59 | 80 |
2 | 1001 | 9001 | 2021-05-02 10:01:01 | (NULL) | (NULL) |
3 | 1001 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 75 |
4 | 1001 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:11:01 | 60 |
5 | 1001 | 9003 | 2021-09-02 12:01:01 | 2021-09-02 12:41:01 | 90 |
6 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:32:00 | 20 |
7 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 |
8 | 1001 | 9004 | 2021-09-03 12:01:01 | (NULL) | (NULL) |
9 | 1002 | 9001 | 2020-01-01 12:01:01 | 2020-01-01 12:31:01 | 99 |
10 | 1002 | 9003 | 2020-02-01 12:01:01 | 2020-02-01 12:31:01 | 82 |
11 | 1002 | 9003 | 2020-02-02 12:11:01 | 2020-02-02 12:41:01 | 76 |
為了得到用戶試卷作答的定性表現,我們將試卷得分按分界點[90,75,60]分為優良中差四個得分等級(分界點劃分到左區間),請統計不同用戶等級的人在完成過的試卷中各得分等級占比(結果保留 3 位小數),未完成過試卷的用戶無需輸出,結果按用戶等級降序、占比降序排序。
由示例數據結果輸出如下:
level | score_grade | ratio |
---|---|---|
3 | 良 | 0.667 |
3 | 優 | 0.333 |
0 | 良 | 0.500 |
0 | 中 | 0.167 |
0 | 優 | 0.167 |
0 | 差 | 0.167 |
解釋:完成過試卷的用戶有 1001、1002;完成了的試卷對應的用戶等級和分數等級如下:
uid | exam_id | score | level score_grade |
---|---|---|---|
1001 | 9001 | 80 | 0 |
1001 | 9002 | 75 | 0 |
1001 | 9002 | 60 | 0 |
1001 | 9003 | 90 | 0 |
1001 | 9001 | 20 | 0 |
1001 | 9002 | 89 | 0 |
1002 | 9001 | 99 | 3 |
1002 | 9003 | 82 | 3 |
1002 | 9003 | 76 | 3 |
因此 0 級用戶(只有 1001)的各分數等級比例為:優 1/6,良 1/6,中 1/6,差 3/6;3 級用戶(只有 1002)各分數等級比例為:優 1/3,良 2/3。結果保留 3 位小數。
思路:
先把 將試卷得分按分界點[90,75,60]分為優良中差四個得分等級這個條件寫出來,這里可以用到case when
CASEWHEN a.score >= 90 THEN'優'WHEN a.score < 90 AND a.score >= 75 THEN'良'WHEN a.score < 75 AND a.score >= 60 THEN'中' ELSE '差'
END
這題的關鍵點就在于這,其他剩下的就是條件拼接了
答案:
SELECT a.LEVEL,a.score_grade,ROUND(a.cur_count / b.total_num, 3) AS ratio
FROM(SELECT b.LEVEL AS LEVEL,(CASEWHEN a.score >= 90 THEN '優'WHEN a.score < 90AND a.score >= 75 THEN '良'WHEN a.score < 75AND a.score >= 60 THEN '中'ELSE '差'END) AS score_grade,count(1) AS cur_countFROM exam_record aLEFT JOIN user_info b ON a.uid = b.uidWHERE a.submit_time IS NOT NULLGROUP BY b.LEVEL,score_grade) a
LEFT JOIN(SELECT b.LEVEL AS LEVEL,count(b.LEVEL) AS total_numFROM exam_record aLEFT JOIN user_info b ON a.uid = b.uidWHERE a.submit_time IS NOT NULLGROUP BY b.LEVEL) b ON a.LEVEL = b.LEVEL
ORDER BY a.LEVEL DESC,ratio DESC
3、限量查詢
3.1、注冊時間最早的三個人
描述:
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人1號 | 19 | 0 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人2號 | 1200 | 3 | 算法 | 2020-02-01 10:00:00 |
3 | 1003 | 機器人3 號 ♂ | 22 | 0 | 算法 | 2020-01-02 10:00:00 |
4 | 1004 | 機器人 4號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
5 | 1005 | 機器人555號 | 2000 | 7 | C++ | 2020-01-11 10:00:00 |
6 | 1006 | 666666 | 3000 | 6 | C++ | 2020-11-01 10:00:00 |
請從中找到注冊時間最早的 3 個人。由示例數據結果輸出如下:
uid | nick_name | register_time |
---|---|---|
1001 | 機器人1號 | 2020-01-01 10:00:00 |
1003 | 機器人 3 號 ♂ | 2020-01-02 10:00:00 |
1004 | 機器人 4 號 | 2020-01-02 11:00:00 |
解釋:按注冊時間排序后選取前三名,輸出其用戶 ID、昵稱、注冊時間。
答案:
SELECT uid,nick_name,register_time
FROM user_info
ORDER BY register_time
LIMIT 3
3.2、注冊當天就完成了試卷的名單第三頁(較難)
現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人 1 | 19 | 0 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人 2 號 | 1200 | 3 | 算法 | 2020-01-01 10:00:00 |
3 | 1003 | 機器人 3 號 ♂ | 22 | 0 | 算法 | 2020-01-01 10:00:00 |
4 | 1004 | 機器人 4 號 | 25 | 0 | 算法 | 2020-01-01 10:00:00 |
5 | 1005 | 機器人 555 號 | 4000 | 7 | 算法 | 2020-01-11 10:00:00 |
6 | 1006 | 機器人 6 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
7 | 1007 | 機器人 7 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
8 | 1008 | 機器人 8 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
9 | 1009 | 機器人 9 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
10 | 1010 | 機器人 10 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
11 | 1011 | 666666 | 3000 | 6 | C++ | 2020-01-02 10:00:00 |
試卷信息表 examination_info
(exam_id
:試卷 ID, tag
:試卷類別, difficulty
:試卷難度, duration
:考試時長, release_time
:發布時間),示例數據如下:
id | exam_id | tag | difficulty | duration | release_time |
---|---|---|---|---|---|
1 | 9001 | 算法 | hard | 60 | 2020-01-01 10:00:00 |
2 | 9002 | 算法 | hard | 80 | 2020-01-01 10:00:00 |
3 | 9003 | SQL | medium | 70 | 2020-01-01 10:00:00 |
現有試卷作答記錄表 exam_record
(uid
用戶 ID,exam_id
試卷 ID, start_time
開始作答時間, submit_time
交卷時間, score
得分) 示例數據如下:
id | uid | exam_id | start_time | submit_time | score |
---|---|---|---|---|---|
1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:59 | 80 |
2 | 1002 | 9003 | 2020-01-20 10:01:01 | 2020-01-20 10:10:01 | 81 |
3 | 1002 | 9002 | 2020-01-01 12:11:01 | 2020-01-01 12:31:01 | 83 |
4 | 1003 | 9002 | 2020-01-01 19:01:01 | 2020-01-01 19:30:01 | 75 |
5 | 1004 | 9002 | 2020-01-01 12:01:01 | 2020-01-01 12:11:01 | 60 |
6 | 1005 | 9002 | 2020-01-01 12:01:01 | 2020-01-01 12:41:01 | 90 |
7 | 1006 | 9001 | 2020-01-02 19:01:01 | 2020-01-02 19:32:00 | 20 |
8 | 1007 | 9002 | 2020-01-02 19:01:01 | 2020-01-02 19:40:01 | 89 |
9 | 1008 | 9003 | 2020-01-02 12:01:01 | 2020-01-02 12:20:01 | 99 |
10 | 1008 | 9001 | 2020-01-02 12:01:01 | 2020-01-02 12:31:01 | 98 |
11 | 1009 | 9002 | 2020-01-02 12:01:01 | 2020-01-02 12:31:01 | 82 |
12 | 1010 | 9002 | 2020-01-02 12:11:01 | 2020-01-02 12:41:01 | 76 |
13 | 1011 | 9001 | 2020-01-02 10:01:01 | 2020-01-02 10:31:01 | 89 |
找到求職方向為算法工程師,且注冊當天就完成了算法類試卷的人,按參加過的所有考試最高得分排名。排名榜很長,我們將采用分頁展示,每頁 3 條,現在需要你取出第 3 頁(頁碼從 1 開始)的人的信息。
由示例數據結果輸出如下:
uid | level | register_time | max_score |
---|---|---|---|
1010 | 0 | 2020-01-02 11:00:00 | 76 |
1003 | 0 | 2020-01-01 10:00:00 | 75 |
1004 | 0 | 2020-01-01 11:00:00 | 60 |
解釋:除了 1011 其他用戶的求職方向都為算法工程師;算法類試卷有 9001 和 9002,11 個用戶注冊當天都完成了算法類試卷;計算他們的所有考試最大分時,只有 1002 和 1008 完成了兩次考試,其他人只完成了一場考試,1002 兩場考試最高分為 81,1008 最高分為 99。
按最高分排名如下:
uid | level | register_time | max_score |
---|---|---|---|
1008 | 0 | 2020-01-02 11:00:00 | 99 |
1005 | 7 | 2020-01-01 10:00:00 | 90 |
1007 | 0 | 2020-01-02 11:00:00 | 89 |
1002 | 3 | 2020-01-01 10:00:00 | 83 |
1009 | 0 | 2020-01-02 11:00:00 | 82 |
1001 | 0 | 2020-01-01 10:00:00 | 80 |
1010 | 0 | 2020-01-02 11:00:00 | 76 |
1003 | 0 | 2020-01-01 10:00:00 | 75 |
1004 | 0 | 2020-01-01 11:00:00 | 60 |
1006 | 0 | 2020-01-02 11:00:00 | 20 |
每頁 3 條,第三頁也就是第 7~9 條,返回 1010、1003、1004 的行記錄即可。
思路:
-
每頁三條,即需要取出第三頁的人的信息,要用到limit
-
統計求職方向為算法工程師且注冊當天就完成了算法類試卷的人的信息和每次記錄的得分,先求滿足條件的用戶,后用 left join 做連接查找信息和每次記錄的得分
答案:
SELECT ui.uid,ui.`level`,ui.register_time,MAX(score) AS max_score
FROM exam_record er
INNER JOIN examination_info ei USING(exam_id)
INNER JOIN user_info ui ON er.uid = ui.uid AND DATE(er.submit_time) = DATE(ui.register_time)
WHERE ui.job = '算法'AND ei.tag = '算法'
GROUP BY ui.uid,ui.`level`,ui.register_time
ORDER BY max_score DESC
LIMIT 6,3
4、文本轉換函數
4.1、修復串列了的記錄
試卷信息表 examination_info
(exam_id
:試卷 ID, tag
:試卷類別, difficulty
:試卷難度, duration
:考試時長, release_time
:發布時間),示例數據如下:
id | exam_id | tag | difficulty | duration | release_time |
---|---|---|---|---|---|
1 | 9001 | 算法 | hard | 60 | 2021-01-01 10:00:00 |
2 | 9002 | 算法 | hard | 80 | 2021-01-01 10:00:00 |
3 | 9003 | SQL | medium | 70 | 2021-01-01 10:00:00 |
4 | 9004 | 算法,medium,80 | 0 | 2021-01-01 10:00:00 |
錄題同學有一次手誤將部分記錄的試題類別 tag、難度、時長同時錄入到了 tag 字段,請幫忙找出這些錄錯了的記錄,并拆分后按正確的列類型輸出。
由示例數據結果輸出如下:
exam_id | tag | difficulty | duration |
---|---|---|---|
9004 | 算法 | medium | 80 |
思路:
先來學習下本題要用到的函數
SUBSTRING_INDEX
函數用于提取字符串中指定分隔符的部分。它接受三個參數:原始字符串、分隔符和指定要返回的部分的數量。
以下是SUBSTRING_INDEX
函數的語法:
SUBSTRING_INDEX(str, delimiter, count)
str
:要進行分割的原始字符串。delimiter
:用作分割的字符串或字符。count
:指定要返回的部分的數量。- 如果
count
大于 0,則返回從左邊開始的前count
個部分(以分隔符為界)。 - 如果
count
小于 0,則返回從右邊開始的前count
個部分(以分隔符為界),即從右側向左計數。
- 如果
下面是一些示例,演示了 SUBSTRING_INDEX
函數的使用:
- 提取字符串中的第一個部分:
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', 1);
-- 輸出結果:'apple'
- 提取字符串中的最后一個部分:
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', -1);
-- 輸出結果:'cherry'
- 提取字符串中的前兩個部分:
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', 2);
-- 輸出結果:'apple,banana'
- 提取字符串中的最后兩個部分:
SELECT SUBSTRING_INDEX('apple,banana,cherry', ',', -2);
-- 輸出結果:'banana,cherry'
答案:
SELECTexam_id,substring_index( tag, ',', 1 ) tag,substring_index( substring_index( tag, ',', 2 ), ',',- 1 ) difficulty,substring_index( tag, ',',- 1 ) duration
FROMexamination_info
WHEREdifficulty = ''
4.2、對過長的昵稱截取處理
描述:現有用戶信息表 user_info
(uid
用戶 ID,nick_name
昵稱, achievement
成就值, level
等級, job
職業方向, register_time
注冊時間),數據如下:
id | uid | nick_name | achievement | level | job | register_time |
---|---|---|---|---|---|---|
1 | 1001 | 機器人 1 | 19 | 0 | 算法 | 2020-01-01 10:00:00 |
2 | 1002 | 機器人 2 號 | 1200 | 3 | 算法 | 2020-01-01 10:00:00 |
3 | 1003 | 機器人 3 號 ♂ | 22 | 0 | 算法 | 2020-01-01 10:00:00 |
4 | 1004 | 機器人 4 號 | 25 | 0 | 算法 | 2020-01-01 11:00:00 |
5 | 1005 | 機器人 567890123 號 | 4000 | 7 | 算法 | 2020-01-11 10:00:00 |
6 | 1006 | 機器人 67890123456789 號 | 25 | 0 | 算法 | 2020-01-02 11:00:00 |
有的用戶的昵稱特別長,在一些展示場景會導致樣式混亂,因此需要將特別長的昵稱轉換一下再輸出,請輸出字符數大于 10 的用戶信息,對于字符數大于 17 的用戶輸出前 10 個字符然后加上三個點號:『…』。
由示例數據結果輸出如下:
uid | nick_name |
---|---|
1005 | 機器人 567890123 號 |
1006 | 機器人 678901234567… |
解釋:字符數大于 10 的用戶有 1005 和 1006,長度分別為 17、22;因此需要對 1006 的昵稱截斷輸出。
思路:
這題涉及到字符的計算,要計算字符串的字符數(即字符串的長度),可以使用 LENGTH
函數或 CHAR_LENGTH
函數。這兩個函數的區別在于對待多字節字符的方式。
LENGTH
函數:它返回給定字符串的字節數。對于包含多字節字符的字符串,每個字符都會被當作一個字節來計算。
示例:
SELECT LENGTH('你好'); -- 輸出結果:6,因為 '你好' 中的每個漢字每個占3個字節
CHAR_LENGTH
函數:它返回給定字符串的字符數。對于包含多字節字符的字符串,每個字符會被當作一個字符來計算。
示例:
SELECT CHAR_LENGTH('你好'); -- 輸出結果:2,因為 '你好' 中有兩個字符,即兩個漢字
答案:
SELECT uid,(CASE WHEN CHAR_LENGTH( nick_name ) > 17 THENCONCAT(SUBSTR(nick_name,1,17),'...') ELSE nick_nameEND) AS nick_name
FROM user_info
WHERE CHAR_LENGTH(nick_name) > 10
好文推薦:
《【SQL】SQL常見面試題總結(1)》
《【SQL】SQL常見面試題總結(2)》
《【SQL】SQL常見面試題總結(3)》