我有一个由唯一ID和一些其他属性组成的表。它持有“时间表”。然后我有另一个表,其中包含每个计划已经或将“触发”的所有时间的列表。这不是确切的架构,但它很接近:
create table schedule (
id varchar(40) primary key,
attr1 int,
attr2 varchar(20)
);
create table schedule_times (
id varchar(40) foreign key schedule(id),
fire_date date
);
我想在Java中查询调度表,获取属性以及下一个和之前的fire_dates,有时会对其中一个属性进行排序,但有时会在之前的fire_date或下一个fire_date中进行排序。通过属性排序很容易,我只是在构建我准备好的语句时将“order by”粘贴到字符串中。我甚至不确定如何在单个查询中选择最后一个fire_date和下一个fire_date - 我知道我可以通过执行
找到给定id的下一个fire_dateSELECT min(fire_date)
FROM schedule_times
WHERE id = ? AND
fire_date > sysdate;
以及使用max()
和fire_date < sysdate
的上一次fire_date的类似内容。我只是简单地说明了如何将其合并到一个选项中,这样我就可以一次性获得下一个和之前的fire_date,以及如何按这些属性中的任何一个进行排序。
答案 0 :(得分:4)
您可以使用Left Join
中的两个子查询来执行此操作
如果没有下一个/上一个时间表,这样做的好处就是为fire_dates返回NULL
。
Select id, attr1, attr2, next_fire_date, previous_fire_date
From schedule s
Left Join ( Select id, Min(fire_date) As next_fire_date
From schedule_times st
Where st.fire_date > Sysdate
Group By id ) n
On ( n.id = s.id )
Left Join ( Select id, Max(fire_date) As previous_fire_date
From schedule_times st
Where st.fire_date < Sysdate
Group By id ) p
On ( p.id = s.id )
然后,您可以在ORDER BY
或next_fire_date
上添加previous_fire_date
。
如果性能很重要,请在schedule_times( id, fire_date )
上创建复合索引,这将允许子查询只读取此索引。
答案 1 :(得分:3)
尝试这样的事情:
select schedule.*,
(
select max(si.fire_date) from schedule_times si where si.id = schedule.id and si.fire_date < sysdate
) as prevfire,
(
select min(si.fire_date) from schedule_times si where si.id = schedule.id and si.fire_date > sysdate
) as nextfire
from schedule
where id = ?
order by attr1
答案 2 :(得分:0)
将查询修改为
SELECT 区别 S.ID,ATTR1,ATTR2, LEAD(FIRE_DATE,1, SYSDATE )OVER(由S.ID分配的S.ID ORDER)NEXT_FIRE_DATE, LAG(FIRE_DATE,1, SYADATE )OVER(由S.ID分配的S.ID ORDER)PREV_FIRE_DATE 来自SCHEDULE S,SCHEDULE_TIMES ST,其中ST.ID = S.ID;
这是简单的查询。你可以尝试这个。
LEAD能够计算下一行(将在当前行之后的行)上的表达式,并将值返回到当前行。 LEAD的一般语法如下所示:
LEAD(sql_expr,offset,default)OVER(analytic_clause)
LAG的语法类似,只是LAG的偏移量会进入前一行。