MySQL按日期排序,其中日期> =今天首先升序,然后日期<今天以降序查询1

时间:2019-08-21 04:53:50

标签: mysql sql sql-order-by

我尝试使用

SELECT *
FROM `activity`
WHERE 1
ORDER BY
    CASE WHEN `activity_date` >= '2019-06-14' THEN `activity_date` END ASC,
    CASE WHEN `activity_date` < '2019-06-14' THEN `activity_date` END DESC,
    `activity_date` ASC

但是它给了我2019-06-14之前的降序顺序,等于或晚于2019-06-14之后的升序顺序。喜欢

+----+------------+
| ID | Date       |
+----+------------+
| 5  | 2019-06-12 |
| 3  | 2019-06-11 |
| 2  | 2019-06-10 |
| 4  | 2019-06-15 |
| 1  | 2019-06-16 |
+----+------------+

目前,我将其分为2个查询,以确保它可以使用WHERE子句返回正确的顺序。

但是,当我需要在许多页面中列出结果时,因为它们具有自己的行数,所以不能使用LIMIT start_limit, items_per_page

如果我使用UNION合并结果,则顺序将再次不正确。因此,如果我可以使用1个单个查询并且可以返回正确的顺序,那就太好了!

3 个答案:

答案 0 :(得分:2)

这是编写ORDER BY子句的一种更为简洁的方法:

SELECT ID, Date
FROM activity
ORDER BY
    Date < '2019-06-14',
    IF(Date >= '2019-06-14', 1, -1) * DATEDIFF(Date, '2019-06-14');

第一个排序级别将记录放在2019-06-14上或之后,然后是较早的记录。然后,在这两个组的每一个中,我们对升序排序以用于以后的记录,而对降序排序用于在前的记录。

enter image description here

Demo

一种适用于任何数据库的更通用的解决方案(保存DATEDIFF,这是特定于MySQL的):

ORDER BY
    CASE WHEN Date < '2019-06-14' THEN 1 ELSE 0 END,
    (CASE WHEN Date >= '2019-06-14' THEN 1 ELSE -1 END) *
     DATEDIFF(Date, '2019-06-14');

答案 1 :(得分:1)

您可以使用以下查询:

SELECT * 
FROM activity
ORDER BY activity_date >= '2019-06-14' DESC,
         CASE WHEN activity_date >= '2019-06-14' THEN activity_date END ASC,
         CASE WHEN activity_date <  '2019-06-14' THEN activity_date END DESC

它使用标志(activity_date >= '2019-06-14')确保活动日期首先排在2019-06-14之后,然后两个大小写表达式确保这些日期排在上升的日期,日期在2019-06-14之前下降。

Demo on dbfiddle

答案 2 :(得分:1)

实际上,您的技术实际上没有任何问题,纯粹是您的第一种情况,当日期小于14时不输出任何内容,因此它输出NULL,并且null的值低于某个值,因此它们都日期小于第14位时按开始顺序排序:

enter image description here

感谢尼克提供了允许该镜头的dbfiddle

要整理出绑定在空MySQL上的这些行,然后查看orderby中的第二个子句,最后得到所有第14个前日期在第14个后日期之前

最简单的解决方法是在以下情况下将高日期作为ELSE:

SELECT *
FROM `activity`
ORDER BY
    CASE WHEN `activity_date` >= '2019-06-14' THEN `activity_date` ELSE '2999-01-01' END ASC,
    CASE WHEN `activity_date` < '2019-06-14' THEN `activity_date` END DESC

这将使屏幕快照中的所有空值变为2099-01-01(按时间顺序在真实日期之后),因此第一种排序会将其放在结果的末尾而不是开始。您发布的所有第14个日期都排在最前面,所有约会的前日期都绑定为2999-01-01,然后MySQL将使用第二个子句来整理联系

简而言之,是因为空值首先出现,并且将所有前置日期都转换为空值的第一种情况,将它们放在结果的顶部


但是,这并不是特别能说明问题的原因,为什么查询中的日期可能是2999,在这种情况下,我总是更倾向于使用更明确的排序。如果您先使用彼此先进行排序的东西(例如整数)来进行粗略的排序,那么

SELECT *
FROM `activity`
ORDER BY
    CASE WHEN `activity_date` >= '2019-06-14' THEN 0 ELSE 1 END,
    CASE WHEN `activity_date` >= '2019-06-14' THEN `activity_date` END ASC,
    CASE WHEN `activity_date` < '2019-06-14' THEN `activity_date` END DESC

那么,很明显,您打算使第14个帖子排在第一位,而下一位开发人员无需记住并意识到空值排在第一位

输出如下:

2019-06-14 --sorted by 0, then date
2019-06-15 --sorted by 0, then date
2019-06-16 --sorted by 0, then date
2019-06-13 --sorted by 1, then date
2019-06-12 --sorted by 1, then date
2019-06-11 --sorted by 1, then date

作为一种常规技术,您可以在案例中添加任意数量的whens(使用不同的整数)以进行更多排序:

SELECT *
FROM `activity`
ORDER BY
    CASE 
      WHEN activityrating = 'gold' THEN -1 
      WHEN `activity_date` >= '2019-06-14' THEN 0 
      ELSE 1 
    END,
...

首先放置所有黄金活动,按日期排序,然后放置所有第14个活动,依此类推