我正在努力优化以下查询(现在需要1:15分钟),但我最好先解释一下我在做什么(长):
我正在为tt_actualstart - tt_actualfinish
标识的员工tt_emp_id
期间选择(Developer Express)日历活动。
这些事件的特征是tt_type值:
0: single event<br />
1: master recurring event<br />
other: exceptions on the recurring events.
(These have a `tt_parentid` referencing `tt_calendar_id` of the master event)
4'OR'-ed查询部分是:
示意性地:
Legend: |-------------------| = selection period
CAPITALS = selected event
lowercase = related event
1. MASTER
|-------------------|
2. EXCEPTION master
|-------------------|
3. master EXCEPTION
|-------------------|
4. MASTER exception
|-------------------|
有一个复杂因素影响了这些查询:我无法选择具有所需员工ID的异常。这是因为当Developer Express代码等于master父级的属性时,Developer Express代码不存储异常的约会属性。因此,只能在主父母上完成对员工ID的选择。
如您所见,第二个OR-ed查询使用第一个OR-ed查询作为子查询;同样为4和3。
select c.*
from tt_calendar c
where
(
(
(c.tt_type in (0,1)) and (c.tt_actualstart <= '2014-03-31') and (c.tt_actualfinish >= '2014-01-01') and (c.tt_emp_id= 20652)
)
or
(
(c.tt_type > 1) and (c.tt_parentid is not null) and
(c.tt_parentid in (select c2.tt_calendar_id from tt_calendar c2
where (c2.tt_calendar_id=c.tt_parentid) and (c2.tt_actualstart <= '2014-03-31') and (c2.tt_actualfinish >= '2014-01-01') and (c2.tt_emp_id=20652)
)
)
)
or
(
(c.tt_type > 1) and (c.tt_parentid is not null) and
(c.tt_actualstart <= '2014-12-31') and (c.tt_actualfinish >= '2014-01-01') and
(c.tt_parentid in (select c2.tt_calendar_id from tt_calendar c2 where c2.tt_emp_id=20652))
)
or
(
(c.tt_type = 1) and
(c.tt_calendar_id in
(select tt_parentid from tt_calendar c2
where (c2.tt_type > 1) and (c2.tt_parentid is not null) and
(c2.tt_actualstart <= '2014-03-31') and (c2.tt_actualfinish >= '2014-01-01') and (c2.tt_emp_id=20652)))
)
)
在tt_actualstart
和tt_actualfinish
上添加索引可以提高15%的速度。 (FireBird)查询计划显示确实正在使用这些索引
除主键tt_calendar_id
外没有其他索引。
我尝试过的另一件事是使用整数TAG字段,该字段由4个单独的UPDATE查询设置,然后选择TAGged记录。
这实际上会增加执行时间。
我不确定converting the IN to EXISTS是否有用 - Firebird / SQL / Oracle(我需要三个)都已经优化了吗?
关于如何改进此查询的更多想法?
2014年2月17日新增
在我的测试数据中有一个异常情况,到目前为止所有的答案都错过了,我的(重)第4个查询发现:
(未找到)仅发生两次事件的重复事件的主ID 27274:2013年12月10日 - 2013年12月11日
与
(发现)例外情况27275,其中发生的事件(从2013年12月11日起)移至2014年1月11日(tt_parent_id = 27274)
在这种情况下,事件被移入选择期间,但主人不在那里。我也需要找到主人。
BTW这四个结果集有一些重叠,因此在所有情况下都应该是UNION而不是UNION ALL,但我的问题并不清楚。
答案 0 :(得分:0)
select c.*
from tt_calendar c
where
(
(c.tt_type in (0,1)) and (c.tt_actualstart <= '2014-12-31') and (c.tt_actualfinish >= '2014-01-01') and (c.tt_emp_id= 20652)
)
UNION
select c.*
from tt_calendar c
inner join tt_calendar c2 on c2.tt_calendar_id=c.tt_parentid
where
(
(c.tt_type > 1) and (c.tt_parentid is not null) and
(c2.tt_actualstart <= '2014-12-31') and (c2.tt_actualfinish >= '2014-01-01') and (c2.tt_emp_id=20652)
)
UNION
select c.*
from tt_calendar c
inner join tt_calendar c2 on c2.tt_calendar_id=c.tt_parentid
where
(
(c.tt_type > 1) and (c.tt_parentid is not null) and
(c.tt_actualstart <= '2014-12-31') and (c.tt_actualfinish >= '2014-01-01') and (c2.tt_emp_id=20652)
)
UNION
select c.*
from tt_calendar c
inner join tt_calendar c2 on c.tt_calendar_id=c2.tt_parentid
where
(
(c.tt_type = 1) and (c.tt_emp_id=20652) and
(c2.tt_type > 1) and (c2.tt_parentid is not null) and
(c2.tt_actualstart <= '2014-12-31') and (c2.tt_actualfinish >= '2014-01-01')
)
)