选择最接近但不大于行的行

时间:2012-03-26 12:36:54

标签: sql oracle

给定一个表格动作(开始:DATE,长度:NUMBER,类型:NUMBER),所有记录都是唯一的,我需要在时间X之前选择(例如)类型为Y的最后一个动作的长度:

select action.length 
 where action.type = Y 
   and action.start is the biggest, but not greater than X

建议的解决方案(改进):

  with actionView as (select * from action where type = Y and time <= X) 
select length
  from actionView
 where time = (select max(time) from actionView)

但这仍然包含两个选择。

我想问的是,是否可以对此查询执行某些分析或分层或任何其他oracle魔法,以改进它?

(可能这样的算法就像我需要的那样,但我不知道如何在SQL中表达它:

savedAction.time = MinimalTime
foreach action in actions
  if action.type = y and savedAction.time < action.time <= X
    savedAction = action
return savedAction;

3 个答案:

答案 0 :(得分:3)

Oracle与其他RDBMS一样没有LIMIT(PostgreSQL,MySQL)或TOP(SQL Server)子句。但你可以使用ROWNUM:

SELECT *
FROM  (
    SELECT length 
    FROM   action
    WHERE  type = Y 
    AND    start < X
    ORDER  BY start DESC
    )
WHERE rownum = 1;

这样,表格只会被查询一次 The details in the manual


在回复Dems评论时,我引用上面的链接:

  

如果在子查询中嵌入ORDER BY子句并放置ROWNUM   在顶级查询中的条件,然后您可以强制ROWNUM   在排序行之后应用的条件。

答案 1 :(得分:2)

您可以使用ROW_NUMBER()在单次扫描中对此进行评估...

WITH
  sequenced_data
AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY x ORDER BY start DESC) AS sequence_id,
    *
  FROM
    action
  WHERE
    type = Y
    AND start < Z
)
SELECT
  *
FROM
  sequenced_data
WHERE
  sequence_id = 1

您不需要PARTITION BY,但会在每个集合中获取“最大”行的位置使用它(例如数据库中的每个人或项目)。

答案 2 :(得分:0)

我不知道任何魔法,但是:

  with (select length, time from action where type = Y and time <= X) as typed_action
  select length from typed_action
  where time = (select max(time) from typed_action)

是否会减少执行的“where”子句和(更多?)较小的临时typed_action表。