다음 요구 사항이 있습니다.Oracle sql 쿼리를 최적화해야합니다.
특정 날짜 (당일) 및 특정 상점 (예 : 12)에 대한 스탭의 채용 일정을 가져오고 싶습니다. 또, 다른 가게 (13) 직원이 와서 가게 (12)에 가게되고, 가게 12 직원이 다른 가게에서 일할 수있는 시나리오가 있습니다.
직원이 출석을 표시하는 경우 상태 테이블에 현재/부재 세부 정보가 저장됩니다.
나는 을 가져오고 싶습니다. 1) staffstatus에 상관없이 staffschedules에서 상점 12에 대한 스태프의 일정은 특정 날짜에 항목이 있거나 없는지 확인하십시오. 항목이 상태 테이블에있는 경우
2) 다른 모든 상점에서이고 staffstatus를 참조하여 다른 매장에 가서 직원의 일정을 거부 staffschedules에서 스케줄 (, 나는
), 검색 할 아무것도 필요하지 않습니다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
이 문제에서 저를 도와주세요. 사전에
덕분에
두 테이블의 테이블 구조는 무엇입니까? 왜 두 테이블 모두에 '저장'해야합니까? 원래 '매장 12'에 있던 직원도 직원 상태에 있습니까? – RedBaron
설명 계획 출력과 어떤 색인이 존재하는지 등을 표시하십시오. 우리는 독자를 신경 쓰지 않습니다. – OldProgrammer
Explain plan이 업데이트되었습니다. 보세요, 당신의 요점을 공유하십시오. – user2556379