【问题标题】:MySQL multidirectional ORDER BYMySQL 多向 ORDER BY
【发布时间】:2015-09-29 15:31:11
【问题描述】:

我有一个表,其中包含存储时间戳的“时间”列。我想对它进行排序,以便如果时间戳在未来(即大于 PHP 的 time() 函数返回的值),它会按升序排序。如果不是在未来,则按价值降序排列。

编辑: 假设我有这个时间戳列表(我知道它们不是实际的,但为了简单起见):

1896
779
468
1478
846
1384

然后假设当前时间戳是'1000'。该列表应由查询重新排序,如下所示:

1384
1478
1896
846
779
468

因此有效地所有高于 1000 的数据都按 ASC 排序,所有低于 1000 的数据都按 DESC 排序。

【问题讨论】:

  • 请附上一些您需要的示例数据和输出格式?
  • 不清楚吗?我会编辑我的帖子...
  • 未来时间升序查询一次,过去时间降序查询第二次,并与UNION结合。

标签: php mysql time timestamp


【解决方案1】:

你可以在ORDER BY中放一个表达式:

 ORDER BY ts >= NOW() DESC, (ts >= NOW()) * ts ASC, ts DESC 

布尔条件在 MySQL 中返回为 0 或 1。

因此,所有未来的时间戳都按1 DESC, timestamp ASC, [timestamp DESC] 排序,而过去的时间戳按0 DESC, 0 ASC, timestamp DESC 排序,您将得到所需的顺序。

这样可以避免重复谓词,但可能会影响性能。

【讨论】:

  • +1,在这一点上,我更喜欢你的回答,而不是我的,这是一个优雅的解决方案。我不知道这样做是否有任何性能损失,但显然更好
【解决方案2】:

我认为您不能以两种不同的方式按相同的列对相同的查询进行排序,但分两步执行此操作可能会获得相同的结果。您可以运行两个单独的查询并合并结果,或者另一种选择是使用 UNION

假设你现在有:

SELECT * FROM `table` ORDER BY `timestamp`

你可以改写为:

(
    SELECT 
        * 
    FROM 
        `table` 
    ORDER BY 
        `timestamp` DESC 
    WHERE 
        timestamp < NOW()
) 
UNION ALL 
(
    SELECT 
        * 
    FROM 
        `table` 
    ORDER BY 
        `timestamp` ASC 
    WHERE timestamp >= NOW()
)

【讨论】:

  • :current 应该是NOW()
  • @Barmar 对,它可能是 NOW() 函数的结果。我这样添加它是因为这个问题也被标记为 PHP,不仅是 MySQL,而且我认为可能会使用 PDO,并且这些可能是绑定参数。也许在未来的某个时间点,这将需要一个任意时间点,而不仅仅是从 MySQL 服务器的角度来看当前时间戳。
  • @Barmar 但你是对的,考虑到这个问题,NOW() 可能是一个更好的主意,我会编辑答案。谢谢你。
  • 我很想在这里使用UNION ALL,因为你知道不会有任何欺骗......因此可以节省引擎检查。另外+1,因为在某些条件下这可能比我的解决方案更快。
  • @Arth 你是对的,只要只在两个查询之一中处理相等性,我猜不会有任何重复。谢谢你的补充。
猜你喜欢
  • 2016-11-22
  • 2015-02-26
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-22
相关资源
最近更新 更多