mysql 生日排序 查詢生日由近到遠 按照生日排序

昨天在項目中修改了一處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,

思路說一下,該查詢有三種解決方法
        第一種解決方式是通過UNION實現,但是UNION和ORDER BY的使用,需要注意一點小事情,先UNION,後ORDER,或者用兩個中間表UNION兩個中間表,論壇上很多大神有詳細的帖子,如參考:http://www.jb51.net/article/99842.htm
代碼如下:
	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一樣-->

        第二種解決方式是通過計算差值,mysql 函數DAYOFYEAR(birthday),該函數返回會員的生日是該年的第幾天,然後再和今天是該年的第幾天相減(DAYOFYEAR(CURDATE())),SELECT 一箇中間表生成一個字段date_num,大於今天的數值不變,小於今天的加上730天,空值直接爲730,ORDER BY 中間表的date_num
代碼如下:
		  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 也沒有生效?期待你的回答!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章