sql - 范围 : Sort by difference between two dates

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

我想创建一个范围,从最近的日期到最远的日期对数据进行排序。

例如我有 3 个值:

<Value id: 1, date: '2012-12-20'>
<Value id: 2, date: '2012-12-28'>
<Value id: 3, date: '2012-12-31'>

然后我想对最接近给定日期的日期进行排序:2012-12-29
我的结果应该是这个顺序:2, 3, 1
如果我选择 2012-12-30,结果必须是:3, 2, 1

我试过这样的:

scope :order_by_closest_date, lambda{|time| 
  select("*, (date - DATE('#{time}')) AS time").order("time ASC")
}

但是没用。
有关信息:Rails 3.2.9 Ruby 1.9.3 Postgresql 9.1.4。
有什么想法吗?

最佳答案

简单查询

第一个示例根据初始问题使用 date 列。

不确定 Ruby 语法,但正确的 SQL 语句应该是:

SELECT * 
FROM   tbl
ORDER  BY @(date_col - '2012-12-29'::date)

@ being the "absolute value" operator.

切勿使用datetime 作为标识符。虽然在 PostgreSQL 中被允许(有一些限制),但这些是 reserved words in the SQL standard并且它会导致令人困惑的错误消息和可能的意外错误。

卓越的性能

根据评论中的更新,其余部分使用 timestamp 列。

对于小表或者临时查询,上面的方案就可以了。对于中型或大型表,如果性能很重要,我建议采用更复杂的方法。

Condicio sine qua non 是datetimestamp 列上的索引。像这样:

CREATE INDEX tbl_my_timestamp_idx ON tbl(my_timestamp);

有了索引,下面的查询将 nuke 大表的简单查询的性能:

SELECT *
FROM  (
    (
    SELECT *
    FROM   tbl
    WHERE  my_timestamp >= '2012-12-30 11:32'::timestamp
    ORDER  BY my_timestamp
    LIMIT  3
    )

    UNION ALL
    (
    SELECT *
    FROM   tbl
    WHERE  my_timestamp < '2012-12-30 11:32'::timestamp
    ORDER  BY my_timestamp DESC
    LIMIT  3
    )
    ) x
ORDER  BY @extract('epoch' FROM (my_timestamp - '2012-12-28 11:32'::timestamp))
LIMIT  3;
  • UNION ALL - SELECT 两条腿周围的括号不是可选的。需要对每条腿应用 LIMIT

  • 如果您按其他列排序,请在您的索引中反射(reflect)出来 - 使用 multi-column index在那种情况下。

怎么会这样?

第一个查询使用表达式作为条件。 Postgres 必须为每一行计算一个值,然后按结果排序并选择前几行。小 table 没问题,但大 table 非常昂贵。 O(n)n 是表中的行数。它不能使用普通索引。加上在所有行中排序和挑选获胜者的一些不平凡的成本。
可以在表达式上创建一个索引,这将是最快的,但它只适用于要比较的常量时间戳 - 几乎不是一个现实的用例。

第二个查询根据您在索引中的时间戳找到位置,依次读取接下来几行的元组指针并直接从表中获取它们(或者甚至直接从索引中使用 9.2 中的仅索引扫描)。两次,一次上升,一次下降,因为我们不知道同行如何比较。但这只是 2 x O(log(n)) ( typical b-tree look-up cost ) 仅对少数预选行进行计算。从小样本中选出获胜者的成本很小。

只需使用 EXPLAIN ANALYZE 进行测试.在对真实表的快速测试中,我得到了一个因子 1000,表有 50k 行。而且它会不断扩展以适应更大的表格。

关于sql - 范围 : Sort by difference between two dates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14081768/

相关文章:

mysql查询不同,性能不同

sql - 如何检查 Hive 中是否存在表?

sql - 如何计算运行乘法

ruby-on-rails - 为什么 Font-Awesome 图标不会加载到 Heroku 上的 Rails 应用程序中?

ruby-on-rails - Tomcat错误日志位置?

ruby - "HTTPI tried to user the httpi adapter"使用 Savon SOAP 库时出错

mysql - 对列中的值进行 Group by 子句

ruby-on-rails - Rails 在哪里存储通过在测试期间保存 activerecord 对象创建的数据?

ruby-on-rails - Rails 迁移假定没有关系

ruby-on-rails - ruby 中空白行的正确缩进?