给定一个表格动作(开始: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;
)
答案 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表。