我有以下要求。Oracle sql查詢需要優化
我想獲取特定日期(當天)和特定商店(如12)的員工的工作時間表。此外,還有其他店鋪(13)員工來店工作(12),店鋪12員工可以爲其他店鋪工作的場景。
狀態表存儲了當前/缺席的詳細信息,如果員工標記出席。
我想取 1)員工日程安排員工日程安排,無論員工狀況如何,員工日程安排都不在特定日期。
2)從staffschedules誰都是從其他商店,並拒絕誰,通過參考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
請幫我在這個問題上。
在此先感謝
這兩張表的表結構是什麼?爲什麼你需要在兩個表中存儲?員工是否會出現在員工狀態中? – RedBaron
請顯示解釋計劃輸出,以及存在哪些索引等。我們不介意讀者。 – OldProgrammer
解釋計劃已更新。請看看並分享你的觀點。 – user2556379