【问题标题】:Select the last and next five from the current timestamp in sql从sql中的当前时间戳中选择最后五个和下五个
【发布时间】:2011-08-04 13:07:36
【问题描述】:

我有一个带有 (order_id, timestamp) 的表。时间戳代表未来可能发生的订单交货日期。如何使用一个 select 语句获取从现在开始的最后 5 个订单和从现在开始的下 5 个订单?是否可以在不使用联合查询的情况下在 sql 中执行此操作?像这样,但没有联合:

select * from table where timestamp <= current_timestamp
order by timestamp desc limit 5
union
select * from table where timestamp >= current_timestamp
order by timestamp asc limit 5

【问题讨论】:

  • SQL 不错,但是我觉得从未来选择5个订单还不够好。 (想想timestamp &gt;= current_timestamp 的含义。)真正的 问题是什么?
  • 更新了问题,订单时间戳很可能>= current_timestamp。
  • 您使用什么 DBMS?为什么不想使用 UNION?
  • PostgreSQL。我想一定有比使用联合查询更聪明的方法。但如果我所拥有的已经是最优化的查询,我想我将不得不接受它。
  • 是的,这就是想法,但您应该使用 UNION ALL 而不是 UNION 并将“

标签: sql postgresql timestamp sql-order-by


【解决方案1】:

我认为我们可以使用window function

WITH Numbered AS (
   SELECT
       *, --TODO, pick columns
       ROW_NUMBER() OVER (ORDER BY CASE WHEN timestamp < current_timestamp THEN timestamp ELSE '18000101' END desc) as HistoricRN,
       ROW_NUMBER() OVER (ORDER BY CASE WHEN timestamp >= current_timestamp THEN timestamp ELSE '99991231' END) as FutureRN
    FROM table
)
SELECT
   * --TODO, pick columns
from Numbered
where HistoricRN between 1 and 5 or FutureRN between 1 and 5

注意我已经任意决定如果时间戳完全匹配,它将在未来的行中。您的原始查询将它放在两个组中(但随后 UNION 会消除它),因此如果时间戳完全匹配,您的查询将返回 9 行而不是 10 行。

【讨论】:

  • 我已经在 PostgreSQL 和 SQL Server 中尝试过这种方法,但它不起作用。行号不计入“current_timestamp”,因此检查它们是否在 [1, 5] 中不会返回任何内容。
  • @Bjorn - 你是对的,对不起。我必须在 ORDER BY 子句中移动 CASE 表达式,并在 CASE 表达式不匹配时选择合适的替代日期,以使排序顺序正确。我已经编辑了我的答案。
  • 太棒了,现在可以完美运行了!我想我原来的联合查询效率更高,但这确实是一个非常聪明的解决方案。
【解决方案2】:

我不认为联合是一个坏主意,但您的查询必须得到解决。您需要将查询嵌入到子查询中才能使用 order by 和 limit。

(未在 PostgreSQL 中测试)。

select * from
  (select *
   from table
   where timestamp <= current_timestamp
   order by timestamp desc limit 5) as T
union
select * from 
  (select *
   from table
   where timestamp >= current_timestamp
   order by timestamp asc limit 5) as T

【讨论】:

    【解决方案3】:

    SQL Server 在 TOP 方面提供了一个选项。这里有一些例子

    SELECT TOP 5 order_id, timestamp FROM table WHERE timestamp < current_timestamp
    

    在 WWW 中的快速搜索告诉我,在 Oracle 中没有直接的等价物。你只剩下使用rownum了。如您所知,在排序之前分配了 rownum,您可能无法获得实际结果。这是解决方法

    SELECT e.*
      FROM (SELECT * FROM table WHERE timestamp < current_timestamp ORDER BY empno) e
     WHERE rownum <= 5 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2014-03-26
      • 2014-10-25
      • 2016-08-11
      • 1970-01-01
      相关资源
      最近更新 更多