【问题标题】:rails order by time with reversed 24 hour periodsrails 按时间排序,24 小时倒置
【发布时间】:2013-08-26 11:38:49
【问题描述】:

我有一个模型来存储每个事件都有一个开始时间。

开始时间由 rails 作为 Time 处理,但在 Postgres 中存储为 datetime(我假设),rails 只是忽略日期并将其存储为 2000-01-01...

我遇到的问题是订购它,以便午夜之后开始的事件在之后而不是之前出现。我如何对它们进行不同的排序并在 24 小时内拆分事件,以便在晚上事件的后半部分出现第一个上午 12 小时的事件。 (如果那样的话)

有什么想法吗?

c=Event.last
c.event_items.order(:time_start)

ORDER BY \"event_items\".time_start ASC"

+-----+----------+-----------+-------------------------+---------+-------------------------+-------------------------+
| id  | event_id | artist_id | time_start              | area_id | created_at              | updated_at              |
+-----+----------+-----------+-------------------------+---------+-------------------------+-------------------------+
| 155 | 63       | 111       | 2000-01-01 00:40:00 UTC |         | 2013-08-24 21:21:57 UTC | 2013-08-26 00:07:44 UTC |
| 153 | 63       | 133       | 2000-01-01 01:10:00 UTC |         | 2013-08-24 21:21:57 UTC | 2013-08-26 00:07:44 UTC |
| 152 | 63       | 128       | 2000-01-01 02:00:00 UTC |         | 2013-08-24 21:21:57 UTC | 2013-08-26 00:07:44 UTC |
| 151 | 63       | 148       | 2000-01-01 22:10:00 UTC |         | 2013-08-24 21:21:57 UTC | 2013-08-26 00:07:44 UTC |
| 194 | 63       | 124       | 2000-01-01 23:00:00 UTC |         | 2013-08-26 00:07:44 UTC | 2013-08-26 00:07:44 UTC |
| 154 | 63       | 98        | 2000-01-01 23:50:00 UTC |         | 2013-08-24 21:21:57 UTC | 2013-08-26 00:07:44 UTC |
+-----+----------+-----------+-------------------------+---------+-------------------------+-------------------------+

我希望从 12 小时(24 小时时钟)之前开始的日期在 12 小时 + 之后...

例如,在本例中,我希望订单为 22:10、23:00、23:50、00:40、01:10、02:00

【问题讨论】:

  • 那么您是否希望它们以某种方式排序,以便它们按照当前时间出现的顺序出现?
  • 我不明白,你的问题,对不起!
  • @holden 我尽我所能回答了,我理解你正确吗?

标签: sql ruby-on-rails ruby-on-rails-3 postgresql ruby-on-rails-4


【解决方案1】:

postgres 中有一个date_part 函数,所以我认为你可以这样做

Event.order("CAST(date_part('hour', time_start) AS Integer)/12 DESC,
             CAST(date_part('hour', time_start) AS Integer)%12 ASC")

如果您想将时间分配在不同的模块中,请尝试使用不同的分隔符。

更新

我想我需要详细说明一下。

基本上我提取 time_start timestamphour 部分并将其转换(或 cast)为 integer 我想使用 integer 而不是 time。如果我们简单地将 hour 除以 12,它将给我们一个间隔,请查看上面的 postgres 文档链接以获取更多详细信息。

所以第一个表达式CAST(date_part('hour', time_start) AS Integer)/12 给了我们010 如果 小时12 之前,1 对于 12 以后。这可以满足您的要求,将 12 之后的几小时放在 12 之后的几小时之上。它们将从 23 > 12 排序,然后是 11 > 0,所以不完全是你想要的。

因此第二个CAST(date_part('hour', time_start) AS Integer)%12。这将给出 use 23 => 11, 22 => 10 ... 12 em> => 011 => 11 ... 0 => 0 em> 等等。所以我们可以按升序对它们进行排序。

顺便说一句,这不会对 分钟 进行排序,因此您可能需要添加 time_start ASC 作为第三个排序条件。我认为您也可以将CAST(date_part('hour', time_start) AS Integer) 添加到SELECT 语句并命名,然后仅在ORDER BY 上引用该名称。

希望得到帮助:)

【讨论】:

  • 最后一个问题,我很困惑如何添加分钟作为第三个条件?
  • 只需将 time_start ASC 添加到组合中,这样它就会是 CAST(date_part('hour', time_start) AS Integer)/12 DESC, CAST(date_part('hour', time_start) AS Integer)%12 ASC, time_start ASC
【解决方案2】:

我猜你可以这样做

c = Event.where(:time_start > 12.hours).order(:time_start) << Event.where(:time_start < 12.hours).order(:time_start)

这将一个接一个地连接两个结果并为您提供所需的结果。

【讨论】:

  • >= 的时间比较不起作用。 “ArgumentError:Symbol 与 ActiveSupport::Duration 的比较失败”但我也希望有一种更简洁的方法来使用 order by 子句。 ;-)
  • @holden 好的,感谢您的更正,但我希望您能理解我的回答。
  • 将其更新为正确的语法是一项小工作,所以请这样做,而不是留下这样的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多