題解 | #篩選限定昵稱成就值活躍日期的用戶#
篩選限定昵稱成就值活躍日期的用戶
http://www.fangfengwang8.cn/practice/2ed07ff8f67a474d90523b88402e401b
# 前兩個條件可以從用戶表得到,謂詞、成就值 # 最后一個要篩選用戶uid,新增一列是用戶最近的一次活躍時間 # 臨時表,左連接三個表,新增每個用戶的試卷最新記錄時間和練習(xí)題最新記錄時間 WITH temp_0 AS( SELECT a.uid uid, #DATE_FORMAT(b.start_time, '%Y%m') exam_t, #DATE_FORMAT(c.submit_time, '%Y%m') ques_t, MAX(b.start_time) OVER(PARTITION BY uid) max_exam_t, MAX(c.submit_time) OVER(PARTITION BY uid) max_ques_t FROM user_info a LEFT JOIN exam_record b USING(uid) LEFT JOIN practice_record c USING(uid) ) # 主查詢,限制用戶名和成就值條件,還有最新活躍記錄符合要求的uid SELECT uid, nick_name, achievement FROM user_info WHERE nick_name LIKE '???號' AND achievement BETWEEN 1200 AND 2500 AND uid IN ( SELECT DISTINCT uid FROM temp_0 WHERE DATE_FORMAT(max_exam_t,'%Y%m') = 202109 OR DATE_FORMAT(max_ques_t,'%Y%m') = 202109 )
踩的坑:1.臨時表的聯(lián)結(jié)最先弄成自連接的
2. 最后篩選活躍記錄最先弄成了選擇最大日期
思路:先計算得到每個用戶在試卷和練習(xí)題上的最新活躍日期,再篩選符合要求的uid;最后謂詞限定用戶名,between限制成就值
知識點:%
被用作通配符,表示任意數(shù)量(包括零個)的任意字符。它通常用于模糊匹配
_
(下劃線)是用來匹配任意單個字符的通配符
?
用作一個參數(shù)的占位符,它可以代表任何值,無論長度如何。這些參數(shù)在查詢執(zhí)行之前會被具體的值所替換。
踩的坑的解析:
- 內(nèi)連接 vs 外連接:外連接 (LEFT JOIN) 會保留 user_info 表中的所有記錄,即使在 exam_record 或 practice_record 表中沒有對應(yīng)的記錄。內(nèi)連接 (INNER JOIN) 只會保留那些在 user_info, exam_record 和 practice_record 表中都有匹配記錄的行。如果某個用戶在 exam_record 或 practice_record 表中沒有記錄,那么這個用戶的信息將不會出現(xiàn)在結(jié)果中。
- 結(jié)果集的差異:使用內(nèi)連接,您將僅獲取那些同時在 user_info, exam_record 和 practice_record 表中都有記錄的用戶。這可能導(dǎo)致您丟失那些僅在 user_info 表中有記錄,但在另外兩個表中沒有記錄的用戶數(shù)據(jù)。
- 查詢邏輯的一致性:確保您的業(yè)務(wù)邏輯需要這樣的數(shù)據(jù)篩選。如果您的目的是要找出那些參加過考試且有練習(xí)記錄的用戶,那么內(nèi)連接是合適的。如果您還想包含那些可能只在 user_info 表中有記錄,但在 exam_record 或 practice_record 表中沒有記錄的用戶,那么您應(yīng)該使用外連接。
您提供的 SQL 代碼片段中包含了 DATE_FORMAT
函數(shù)和 IF
函數(shù)的組合。這個組合是用來確定 max_exam_t
和 max_ques_t
兩個日期中較晚的一個,然后將其格式化為 '%Y%m'
格式,并檢查這個日期是否與 '202109' 相等。
原始的代碼片段是這樣的:
WHERE DATE_FORMAT(max_exam_t, '%Y%m') = '202109' OR DATE_FORMAT(max_ques_t, '%Y%m') = '202109'
它檢查 max_exam_t
或 max_ques_t
任一的月份是否為 '202109'。
修改后的代碼片段:
DATE_FORMAT(IF(max_exam_t >= max_ques_t, max_exam_t, max_ques_t), '%Y%m') = '202109'
這個修改后的條件將比較 max_exam_t
和 max_ques_t
的值,取最大的一個(即最晚的日期),然后格式化并檢查是否為 '202109'。
這個改變的意義:
- 原始條件檢查兩個日期中任何一個是否符合特定的月份 '202109'。
- 修改后的條件僅檢查兩個日期中最晚的那個是否符合特定的月份 '202109'。
因此,原始條件可能會選擇更多的記錄,因為它允許任一日期符合條件即可;而修改后的條件更加嚴(yán)格,只有當(dāng)兩個日期中的較晚者符合條件時,記錄才會被選中。這個邏輯上的差異會導(dǎo)致結(jié)果集中可能包含的記錄數(shù)量不同。