按日期排序,过去的日期排在未来日期之后

11

我需要在MySql数据库的一个表上执行查询,使得返回的行按照以下方式排序:

如果今天是10/09/12:

...
11/09/12 
12/09/12
15/09/12
08/09/12  <--here start the past dates
07/09/12
05/09/12
....

有没有一种直接在MySQL中实现这个的方法?


我是这样解决的:

首先,选择语句包括一个新的布尔值,通过判断日期是过去还是未来来标记:

SELECT DISTINCT *,CASE  WHEN startdate < CURDATE() THEN 0
                ELSE 1 END AS past_or_future 

其次,我进行了两次“排序”操作:首先按past_or_future布尔值排序,然后按日期排序,并且条件如下:

ORDER BY past_or_future  DESC , CASE WHEN past_or_future  = 1 THEN startdate END ASC, CASE WHEN past = 0 THEN startdate END DESC

我首先按日期排序获取了所有未来日期(从小到大),然后按日期排序获取了所有过去日期(从大到小)。

3个回答

17

即使在 ORDER BY 子句中,仍然可以使用 CASE 语句。

SELECT *
FROM tableName
ORDER BY (CASE WHEN DATE(dateColumn) < DATE(GETDATE())
              THEN 1
              ELSE 0
         END) DESC, dateColumn ASC

我搜索了几个关于这种排序的答案,发现这个是最简单和最快的。谢谢! - Primoz Rome
4
GETDATE()是MsSQL中的函数,不是MySQL。你可以使用CURDATE()代替。 - Richard

4

是的,一种方法是使用“更强大”的排序键(下面我使用位置而不是列名)将两个查询联合在一起:

select 1 as uberkey, date1, column2
  from mytable
  where data1 >= '2012-10-09'
union all
select 2 as uberkey, date1, column2
  from mytable
  where data1 < '2012-10-09'
order by 1 asc, 2 asc

这段内容涉及到IT技术,将使用uberkey作为主要排序字段,以便后面的日期排在前面。当您显示数据时,可以简单地忽略此列。
这通常比每行函数(如case)更有效率,因为case必须对每行进行翻译。两个带有where子句的查询可以仅使用索引抛弃另一半的行并对检索到的行使用常量来处理,从而更加高效。
就像所有联合查询一样,请确保使用union all,如果两个子查询是互斥的,那么就没有必要进行不必要的排序和去重操作。虽然我不太了解MySQL,但我自己是一个DB2人,聪明的DBMS实际上可以并行执行查询的两个子组件以提高效率。

0

通常情况下,如果不使用 UNION,你无法按同一列进行正序和倒序排序。使用 UNION 也有一些缺点,特别是在使用 ORM 时。如果你想按即将到来的时间升序排序过去的时间降序排序,可以使用如下技巧:

SELECT yourDateColumn,IF(yourDateColumn)

你也可以在使用 ORM 的同时使用它,并且仍然可以使用分页器等等。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接