昨天在項目中修改了一處bug,需求是查詢會員檔案列表,點擊按生日排序,需要將即將過生日的用戶由近至遠的排序。
舉個列子,有一張tbl_user表,表有字段birthday會員生日,birthday有7行內容爲:
'2018.04.01',
'2018.04.02',
'2018.04.03',
'2018.04.04',
'2018.04.05',
'',
NULL,
今天是'2018.04.03',那麼查詢出的結果應爲:
'2018.04.03',
'2018.04.04',
'2018.04.05',
'2018.04.01',
'2018.04.02',
'',
NULL,
SELECT * FROM(
SELECT birthday
FROM tbl_user u
WHERE DATE_FORMAT(birthday,'%m%d') >= DATE_FORMAT(NOW(),'%m%d')
AND birthday IS NOT NULL
AND birthday != ''
ORDER BY DATE_FORMAT(birthday,'%m%d') ASC
) AS t1
UNION
SELECT * FROM(
SELECT birthday
FROM tbl_user u
WHERE DATE_FORMAT(birthday,'%m%d') < DATE_FORMAT(NOW(),'%m%d')
AND birthday IS NOT NULL
AND birthday != ''
ORDER BY DATE_FORMAT(birthday,'%m%d') ASC
) AS t2
UNION
SELECT * FROM(
SELECT birthday
FROM tbl_user u
WHERE DATE_FORMAT(birthday,'%m%d') < DATE_FORMAT(NOW(),'%m%d')
AND birthday IS NULL
AND birthday = ''
ORDER BY DATE_FORMAT(birthday,'%m%d') ASC
) AS t3
<!--這種中間表的方法最終沒能實現我的需求,但這也是一種解決方案,有大佬可以給出答案嗎?可能因爲是查詢的同一張表的問題嗎?,就如update select limit1一樣-->
SELECT * FROM(
SELECT birthday,IF(birthday IS NULL OR birthday ='', 730,IF(DAYOFYEAR(birthday)-DAYOFYEAR(CURDATE())>=0, DAYOFYEAR(birthday)-DAYOFYEAR(CURDATE()) , DAYOFYEAR(birthday)-DAYOFYEAR(CURDATE())+730) ) AS date_num
FROM tbl_user
) AS t1
ORDER BY t1.date_num ASC
第三種解決方式是直接通過ORDER BY解決,需要能理解這句sql的含義,也是相當直接簡潔,正確完美的解決辦法
代碼如下:
SELECT birthday
FROM tbl_user
ORDER BY
IF(birthday IS NULL OR birthday ='', 2, IF(DATE_FORMAT(birthday,'%m.%d')>=DATE_FORMAT(NOW(),'%m.%d'), 0, 1)) ASC,
(DATE_FORMAT(birthday,'%m%d') - DATE_FORMAT(NOW(),'%m%d')) ASC
還可以更逆天的排序,將已過的生日倒敘排列,代碼如下:
SELECT birthday
FROM tbl_user
ORDER BY
IF(birthday IS NULL OR birthday ='', 2, IF(DATE_FORMAT(birthday,'%m.%d')>=DATE_FORMAT(NOW(),'%m.%d'), 0, 1)) ASC,
ABS(DATE_FORMAT(birthday,'%m%d') - DATE_FORMAT(NOW(),'%m%d')) ASC
效果如下:
好了,到這裏就結束了,一個簡單有意思的經典排序,發動大腦,也許你會有更多的辦法,另外,有沒有大神能解答下爲什麼union中間表order by 也沒有生效?期待你的回答!