我有以下要求。
我想获取特定日期(当天)和特定商店(例如12)的员工的工作时间表。此外,还有其他商店(13)员工将来商店(12),商店12名员工可以在其他商店工作。
如果员工标记他们的出勤状态,状态表将存储当前/缺席的详细信息。
我想要取 1)无论员工情况如何,员工时间表中店员12的员工时间表都在特定日期进入。
2)来自其他商店的员工安排的时间表,并通过参考staffstatus拒绝前往其他商店的员工的时间表(如果条目在状态表中,我需要检索,否则没有)
2表:
我写了下面的查询。运行平均需要30秒。在最坏的情况下,93秒。
STAFFSCHEUDLES TABLE SCHEMA:
CREATE TABLE "STAFFSCHEDULES"
(
"STORE_ID" VARCHAR2(75 BYTE) NOT NULL ENABLE,
"START_DATE" DATE NOT NULL ENABLE,
"JOB_ID" VARCHAR2(22 BYTE) NOT NULL ENABLE,
"START_TIME" VARCHAR2(5 BYTE) NOT NULL ENABLE,
"END_DATE" DATE NOT NULL ENABLE,
"END_TIME" VARCHAR2(5 BYTE) NOT NULL ENABLE,
"JOBNAME" VARCHAR2(1500 BYTE)
CONSTRAINT "PK_STAFFSCHEDULES" PRIMARY KEY ("STORE_ID", "START_DATE", "JOB_ID", "START_TIME")
CREATE UNIQUE INDEX "PK_STAFFSCHEDULES" ON "STAFFSCHEDULES"
(
"STORE_ID", "START_DATE", "JOB_ID", "START_TIME"
)
CREATE INDEX "IDX1_STAFFSCHEDULES_STORSTDT" ON "STAFFSCHEDULES"
(
"STORE_ID",
"START_DATE"
)
CREATE INDEX "STAFFSCHEDULES_IDX" ON "STAFFSCHEDULES"
(
"JOB_ID"
)
STAFFSTATUS TABLE SCHEMA:
CREATE TABLE "STAFFSTATUS"
(
"JOB_SEQ_ID" NUMBER(10,0) NOT NULL ENABLE,
"JOB_ID" VARCHAR2(15 BYTE) NOT NULL ENABLE,
"STORE_ID" VARCHAR2(4 BYTE) NOT NULL ENABLE,
"JOB_DATE" DATE NOT NULL ENABLE,
"STATUS" VARCHAR2(1 BYTE) DEFAULT 'N' ,
"SERVER_DATE" DATE
CONSTRAINT "PK_STAFFSTATUS" PRIMARY KEY ("JOB_SEQ_ID")
CONSTRAINT "UK_STAFFSTATUS" UNIQUE ("JOB_ID", "STORE_ID", "JOB_DATE")
)
CREATE INDEX "INDEX_STAFFSTATUS" ON "STAFFSTATUS"
(
"STORE_ID",
"STATUS"
)
CREATE INDEX "INDEX_STAFFSTATUS_JOB_DT" ON "STAFFSTATUS"
(
"STORE_ID",
"JOB_DATE",
"STATUS"
)
CREATE UNIQUE INDEX "PK_STAFFSTATUS" ON "STAFFSTATUS"
(
"JOB_SEQ_ID"
)
CREATE UNIQUE INDEX "UK_STAFFSTATUS" ON "STAFFSTATUS"
(
"JOB_ID", "STORE_ID", "JOB_DATE"
)
CREATE INDEX "INDEX_STAFFSTATUS_UPDT" ON "STAFFSTATUS"
(
"STORE_ID",
"SERVER_DATE"
)
要重新检索时间表:
SELECT *
From StaffSchedules
WHERE store_id='15'
AND ((start_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY')) AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+(1-1/24/60/60)
AND TO_CHAR(start_date,'HH24:MI') <= start_time)
OR((end_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1/24/60/60 AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1)
AND TO_CHAR(end_date,'HH24:MI') >= end_time))
AND job_id NOT IN
(SELECT distinct s2.job_id
FROM staffschedules s2
WHERE s2.store_id=store_id
AND ((s2.start_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY')) AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+(1-1/24/60/60)
AND TO_CHAR(s2.start_date,'HH24:MI') <= s2.start_time)
OR((s2.end_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1/24/60/60 AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1)
AND TO_CHAR(s2.end_date,'HH24:MI') >= s2.end_time))
AND SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,8) = 'NOTALLOCATED')
AND job_id NOT IN (
Select job_Id From staffStatus Where Trunc(job_Date)=Trunc(to_date('07/08/2013','MM/DD/YYYY')) And Store_Id!='15')
UNION ALL
SELECT *
From StaffSchedules ss
Right Outer Join staffStatus status On Es.job_Id=status.job_Id And status.Store_Id<>ss.Store_Id And
(Trunc(status.job_Date)=Trunc(ss.Start_Date) Or Trunc(status.job_Date)=Trunc(ss.End_Date))
AND ((start_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY')) AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+(1-1/24/60/60)
AND TO_CHAR(start_date,'HH24:MI') <= start_time)
OR((end_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1/24/60/60 AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1)
AND TO_CHAR(end_date,'HH24:MI') >= end_time))
AND job_id NOT IN
(SELECT distinct s2.job_id
FROM staffschedules s2
WHERE s2.store_id=store_id
AND ((s2.start_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY')) AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+(1-1/24/60/60)
AND TO_CHAR(s2.start_date,'HH24:MI') <= s2.start_time)
OR((s2.end_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1/24/60/60 AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1)
AND TO_CHAR(s2.end_date,'HH24:MI') >= s2.end_time))
AND SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,8) = 'NOTALLOCATED')
AND status.store_id='15' AND TRUNC(status.job_date)=TRUNC(to_date('07/08/2013','MM/DD/YYYY'))
ORDER BY job_id,start_date,start_time;
执行计划:
----------------------------------------------------------------------------------------------------- -------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------- -------------
| 0 | SELECT STATEMENT | | 41 | 10865 | 37990 (1)| 00:07:36 |
| 1 | SORT ORDER BY | | 41 | 10865 | 37989 (67)| 00:07:36 |
| 2 | UNION-ALL | | | | | |
| 3 | NESTED LOOPS ANTI | | 1 | 265 | 12649 (1)| 00:02:32 |
| 4 | NESTED LOOPS ANTI | | 1 | 146 | 12620 (1)| 00:02:32 |
|* 5 | TABLE ACCESS BY INDEX ROWID| STAFFSCHEDULES | 109 | 13734 | 12401 (1)| 00:02:29 |
|* 6 | INDEX RANGE SCAN | IDX1_STAFFSCHEDULES_STORSTDT | 65068 | | 410 (1)| 00:00:05 |
|* 7 | INDEX RANGE SCAN | UK_STAFFSTATUS | 137K| 2694K| 2 (0)| 00:00:01 |
|* 8 | TABLE ACCESS BY INDEX ROWID | STAFFSCHEDULES | 1 | 119 | 29 (0)| 00:00:01 |
|* 9 | INDEX RANGE SCAN | STAFFSCHEDULES_IDX | 83 | | 2 (0)| 00:00:01 |
| 10 | NESTED LOOPS ANTI | | 40 | 10600 | 25340 (1)| 00:05:05 |
| 11 | NESTED LOOPS | | 40 | 5840 | 24820 (1)| 00:04:58 |
| 12 | TABLE ACCESS BY INDEX ROWID| STAFFSTATUS | 2208 | 44160 | 2931 (1)| 00:00:36 |
|* 13 | INDEX RANGE SCAN | INDEX_STAFFSTATUS_SCHD_DT | 2208 | | 1525 (1)| 00:00:19 |
|* 14 | TABLE ACCESS BY INDEX ROWID| STAFFSCHEDULES | 1 | 126 | 29 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | STAFFSCHEDULES_IDX | 83 | | 2 (0)| 00:00:01 |
|* 16 | TABLE ACCESS BY INDEX ROWID | STAFFSCHEDULES | 1 | 119 | 13 (0)| 00:00:01 |
|* 17 | INDEX RANGE SCAN | PK_STAFFSCHEDULES | 1 | | 12 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------- -------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - filter(("START_DATE"<=TO_DATE(' 2013-07-08 23:59:59', 'syyyy-mm-dd hh24:mi:ss') AND
"START_DATE">=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"START_TIME">=TO_CHAR(INTERNAL_FUNCTION(START_DATE"),'HH24:MI') OR
"END_DATE"<=TO_DATE(' 2013-07-09 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"END_DATE">=TO_DATE(' 2013-07-08 00:00:01', 'syyyy-mm-dd hh24:mi:ss') AND
"END_TIME"<=TO_CHAR(INTERNAL_FUNCTION("END_DATE"),'HH24:MI')))
6 - access("STORE_ID"='15')
7 - access("JOB_ID"="JOB_ID")
filter(TRUNC(INTERNAL_FUNCTION("JOB_DATE"))=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "STORE_ID"<>'15')
8 - filter("S2"."STORE_ID"='15' AND ("S2"."START_DATE"<=TO_DATE(' 2013-07-08 23:59:59',
'syyyy-mm-dd hh24:mi:ss') AND "S2"."START_DATE">=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "S2"."START_TIME">=TO_CHAR(INTERNAL_FUNCTION("S2"."START_DATE"),'HH24:MI'
) OR "S2"."END_DATE"<=TO_DATE(' 2013-07-09 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"S2"."END_DATE">=TO_DATE(' 2013-07-08 00:00:01', 'syyyy-mm-dd hh24:mi:ss') AND
"S2"."END_TIME"<=TO_CHAR(INTERNAL_FUNCTION("S2"."END_DATE"),'HH24:MI')) AND
SUBSTR("S2"."JOBNAME",INSTR("S2"."JOBNAME",'/',1,7)+1,8)='NOTALLOCATED')
9 - access("JOB_ID"="S2"."JOB_ID")
13 - access("STATUS"."STORE_ID"='15')
filter(TRUNC(INTERNAL_FUNCTION("STATUS"."JOB_DATE"))=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd
hh24:mi:ss'))
14 - filter(("START_DATE"<=TO_DATE(' 2013-07-08 23:59:59', 'syyyy-mm-dd hh24:mi:ss') AND
"START_DATE">=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"START_TIME">=TO_CHAR(INTERNAL_FUNCTION("START_DATE"),'HH24:MI') OR
"END_DATE"<=TO_DATE(' 2013-07-09 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"END_DATE">=TO_DATE(' 2013-07-08 00:00:01', 'syyyy-mm-dd hh24:mi:ss') AND
"END_TIME"<=TO_CHAR(INTERNAL_FUNCTION("END_DATE"),'HH24:MI')) AND
"STATUS"."STORE_ID"<>"STORE_ID" AND (TRUNC(INTERNAL_FUNCTION("STATUS"."JOB_DATE"))=TRUNC(INTERNAL_FUNCT
ION("START_DATE")) OR TRUNC(INTERNAL_FUNCTION("STATUS"."JOB_DATE"))=TRUNC(INTERNAL_FUNCTION("
END_DATE"))) AND "STORE_ID"<>'15')
15 - access("STATUS"."JOB_ID"="JOB_ID")
16 - filter(("S2"."STORE_ID"='15' AND ("S2"."START_DATE"<=TO_DATE(' 2013-07-08 23:59:59',
'syyyy-mm-dd hh24:mi:ss') AND "S2"."START_DATE">=TO_DATE(' 2013-07-08 00:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "S2"."START_TIME">=TO_CHAR(INTERNAL_FUNCTION("S2"."START_DATE"),'HH24:MI'
) OR "S2"."END_DATE"<=TO_DATE(' 2013-07-09 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"S2"."END_DATE">=TO_DATE(' 2013-07-08 00:00:01', 'syyyy-mm-dd hh24:mi:ss') AND
"S2"."END_TIME"<=TO_CHAR(INTERNAL_FUNCTION("S2"."END_DATE"),'HH24:MI')) AND
SUBSTR("S2"."JOBNAME",INSTR("S2"."JOBNAME",'/',1,7)+1,8)='NOTALLOCATED')
17 - access("S2"."STORE_ID"="STORE_ID" AND "JOB_ID"="S2"."JOB_ID")
filter("JOB_ID"="S2"."JOB_ID" AND "S2"."STORE_ID"<>'15')
Staffschedule数据示例:
storeid job_id startdate starttime enddate endtime jobname
12 1 2013-07-11 09:00:00 09:00 2013-07-11 18:00:00 10:00 class A
12 1 2013-07-11 09:00:00 10:00 2013-07-11 18:00:00 11:00 class B
12 1 2013-07-11 09:00:00 11:00 2013-07-11 18:00:00 18:00 class C
请帮我解决这个问题。
提前致谢
答案 0 :(得分:1)
好的,问题数据有很大的变化,所以让我们从头开始检查。
首先,在查询文本中提出了一个未指定的内容:
AND SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,8) = 'NOTALLOCATED')
在查询中没有带别名ses2
的表,所以我对如何处理该事情没有任何想法。请注意,它永远不会评估为true
,因为length('NOTALLOCATED')
超过8.因此该条件已从答案中删除。
影响查询性能的主要因素是过度使用NOT IN
条件。在大多数情况下,这些条件必须更改为主查询中针对字段的简单测试
在问题的查询中我们有这样的情况:
select
t.*
from
my_table t
where
<big-basket-of-conditions-here>
and
t.field_1 not in ( select t.field_1
from my_table t
where
<same-big-basket-of-conditions>
and
<one_more_test>
)
必须更改为
select
t.*
from
my_table t
where
<big-basket-of-conditions-here>
and
not (<one-more-test>)
E.g。你有:
AND job_id NOT IN
(SELECT distinct s2.job_id
FROM staffschedules s2
WHERE s2.store_id=store_id
AND ((s2.start_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY')) AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+(1-1/24/60/60)
AND TO_CHAR(s2.start_date,'HH24:MI') <= s2.start_time)
OR((s2.end_date BETWEEN TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1/24/60/60 AND TRUNC(to_date('07/08/2013','MM/DD/YYYY'))+1)
AND TO_CHAR(s2.end_date,'HH24:MI') >= s2.end_time))
AND SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,8) = 'NOTALLOCATED')
可以改为
AND SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,8) <> 'NOTALLOCATED')
没有子查询和NOT IN
如果您需要连接另一个表来执行测试,最好在主选择中执行:do outer join然后测试字段:
select * from (
select
ss.*,
nvl(SUBSTR(ses2.org_path,INSTR(ses2.org_path,'/',1,7)+1,12),'X') alloc_flag
from
staffschedules ss,
some_table ses2
where
ses2.some_field (+) = ss.some_field and ...
)
where alloc_flag <> 'NOTALLOCATED'
这种情况的另一个好例子是这种情况:
AND job_id NOT IN (
Select job_Id
From staffStatus
Where Trunc(job_Date)=Trunc(to_date('07/08/2013','MM/DD/YYYY')) And Store_Id!='15'
)
它包含两件坏事。其中一个在上面讨论过,接下来是条件中!=
的使用。这些条件消除了有效索引使用的任何可能性。对于这种情况最糟糕的是,所有索引都首先有store_id
,因此数据库引擎必须遍历整个索引才能找到所有条件,并且不能回退到job_date
上的另一个索引第一名。
因此,可以使用相同的技术重写该条件
select * from (
select
ss.*,
nvl(statuses.store_id,'X') status_store_id
from
staffschedules ss,
staffstatus statuses
where
statuses.job_id (+) = ss.some_field
Trunc(job_Date (+)) = Trunc(to_date('07/08/2013','MM/DD/YYYY'))
and ...
)
where status_store_id = '15'
最后一件事是加入时字段上的函数用法。 Trunc(job_date)
看起来很直观,但性能不好,因为在这种情况下,数据库无法使用job_date
上的索引。所以在这种情况下更好地使用边界条件:
job_Date >= to_date('07/08/2013','MM/DD/YYYY')
and
job_Date < to_date('07/08/2013','MM/DD/YYYY') + 1
最后,我写了示例查询,获得完整的时间表列表。您可以在this SQLFiddle上进行测试,或者查看下面的内容。 它返回指定商店和日期的完整日程表和状态集 因为我不确定理解调度逻辑,所以您可以自己过滤查询结果。
with params as (
-- Just to write parameters only once.
-- Note that parameter date truncated.
select
trunc(to_date('07/24/2013 07:20','MM/DD/YYYY HH24:MI')) as date_val,
'15' as store_id
from dual
),
store_jobs_from_schedule as (
-- Select all valid schedules on desired date for specified store with corresponding statuses if any.
select
scheduled_jobs.job_id job_id,
scheduled_jobs.store_id schedule_store_id,
scheduled_jobs.start_date schedule_start_date,
scheduled_jobs.start_date_time schedule_start_time,
scheduled_jobs.end_date schedule_end_date,
scheduled_jobs.end_date_time schedule_end_time,
scheduled_jobs.jobname schedule_job_name,
status_list.job_seq_id status_id,
status_list.store_id status_store_id,
status_list.job_date status_job_date,
status_list.status status
from
(
select -- get all schedules for specified date and store.
p.date_val,
schedules.job_id,
schedules.store_id,
schedules.start_date,
( -- Calculate exact start time as date and time value
trunc(schedules.start_date) +
(to_date(schedules.start_time,'hh24:mi') - to_date('00:00','hh24:mi'))
) start_date_time,
schedules.end_date,
( -- Calculate exact end time as date and time value
trunc(schedules.end_date) +
(to_date(schedules.end_time,'hh24:mi') - to_date('00:00','hh24:mi'))
) end_date_time,
schedules.jobname
from
params p,
staffschedules schedules
where
-- scheduled to specified store
schedules.store_id = p.store_id
and
-- start before the end of desired date
schedules.start_date < p.date_val + 1
and
-- end after beginning of desired date
schedules.end_date >= p.date_val
)
scheduled_jobs,
staffstatus status_list
where
-- Check if schedule start time are valid
(scheduled_jobs.start_date <= scheduled_jobs.start_date_time)
and
-- Check if schedule end time are valid
(scheduled_jobs.end_date >= scheduled_jobs.end_date_time)
and
-- Link status by staff and date if any - only on desired date,
-- not for full schedule length
status_list.job_id (+) = scheduled_jobs.job_id
and
status_list.job_date (+) >= scheduled_jobs.date_val
and
status_list.job_date (+) < scheduled_jobs.date_val + 1
),
store_stuff_jobs as (
-- Select all statuses for specified date and store and link it to corresponding schedules if any
select -- clear data in invalid schedules
job_id job_id,
decode(is_valid_schedule,'N', null, schedule_store_id) schedule_store_id,
decode(is_valid_schedule,'N', cast(null as date), schedule_start_date) schedule_start_date,
decode(is_valid_schedule,'N', cast(null as date), schedule_start_time) schedule_start_time,
decode(is_valid_schedule,'N', cast(null as date), schedule_end_date) schedule_end_date,
decode(is_valid_schedule,'N', cast(null as date), schedule_end_time) schedule_end_time,
decode(is_valid_schedule,'N', null, schedule_job_name) schedule_job_name,
status_id status_id,
status_store_id status_store_id,
status_job_date status_job_date,
status status
from (
select -- Calculate if selected schedule are valid
job_id,
schedule_store_id,
schedule_start_date,
schedule_start_time,
schedule_end_date,
schedule_end_time,
schedule_job_name,
status_id,
status_store_id,
status_job_date,
status,
( -- Calculate flag to check if times of schedules are valid
case
when
(schedule_start_date > schedule_start_time)
or
(schedule_end_date < schedule_end_time)
then 'N'
else 'Y'
end
) is_valid_schedule
from (
select
status_list.job_id job_id,
schedules.store_id schedule_store_id,
schedules.start_date schedule_start_date,
( -- Calculate exact start time as date and time value
trunc(schedules.start_date) +
(to_date(schedules.start_time,'hh24:mi') - to_date('00:00','hh24:mi'))
) schedule_start_time,
schedules.end_date schedule_end_date,
( -- Calculate exact end time as date and time value
trunc(schedules.end_date) +
(to_date(schedules.end_time,'hh24:mi') - to_date('00:00','hh24:mi'))
) schedule_end_time,
schedules.jobname schedule_job_name,
status_list.job_seq_id status_id,
status_list.store_id status_store_id,
status_list.job_date status_job_date,
status_list.status status
from
params p,
staffstatus status_list,
staffschedules schedules
where
status_list.job_date >= p.date_val
and
status_list.job_date < p.date_val + 1
and
status_list.store_id = p.store_id
and
-- Link schedules for same staff on same date if any.
-- Even schedules to same store, because we need exactly same
-- record as in first query to eliminate duplicates on last step.
schedules.job_id (+) = status_list.job_id
and
schedules.start_date (+) < trunc(status_list.job_date) + 1 -- start before the end of desired date
and
schedules.end_date (+) >= trunc(status_list.job_date) -- end after beginning of desired date
)
)
)
select
-- records comes from schedules
job_id,
schedule_store_id store_id,
schedule_store_id,
schedule_start_date,
schedule_start_time,
schedule_end_date,
schedule_end_time,
schedule_job_name,
status_id,
status_store_id,
status_job_date,
status
from
store_jobs_from_schedule
union -- duplicates eliminated
select
-- records comes from status
job_id,
status_store_id store_id,
schedule_store_id,
schedule_start_date,
schedule_start_time,
schedule_end_date,
schedule_end_time,
schedule_job_name,
status_id,
status_store_id,
status_job_date,
status
from
store_stuff_jobs
order by
job_id, schedule_start_date, schedule_start_time
答案 1 :(得分:0)
您的主过滤器位于date
。所以你想要按日期索引。但是,只有当日期的记录数远远少于表中的记录数时,这才有意义。说&lt; 5%。所以你的第一个最好的收获是staffschedules.date
的索引(或者从日期开始的其他多部分索引)。
您应该在sqlplus中使用示例日期单独运行两个查询,并查看花费的时间。如果在第一个查询上花费了时间,那么这将是date
索引甚至是date-store
索引。这部分不应该很慢。
如果UNION的第二部分很慢,请将其分成两部分并进行调查:
SELECT *
FROM staffschedules
WHERE date = v_date
AND store <> v_store
和
SELECT staffid
FROM staffstatus
WHERE store=v_store
AND jobdate=v_date
如果第一部分又是慢的日期索引。如果第二个慢,那么它可能需要staffstatus.jobdate
上的索引。如果每个都运行得相当快,那么您必须查看staffid
如何加入,但很可能是jobdate
上的索引。