关于两个查询的问题:
查询A:
SELECT ******
FROM WORK_ORDERS w
LEFT JOIN (
SELECT crew.WO_ID, EMP.DOCUMENT_NUMBER|| '-'|| emp.FIRST_NAME|| ' '|| emp.LAST_NAME helpers
FROM WORK_ORDER_CREW_ASSIGMENTS crew
INNER JOIN EMPLOYEE_CREWS employeeCrew
ON employeeCrew.CREW_ID = crew.CREW_ID AND employeeCrew.IS_RESPONSIBLE = 'N'
INNER JOIN EMPLOYEES emp ON EMP.id = EMPLOYEECREW.EMPLOYEE_ID
WHERE crew.IS_ACTIVE = 'S'
) crewHelpers
ON (w.id = crewHelpers.wo_id)
and w.CREATION_DATE between
to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
and to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
查询B:
SELECT ******
FROM WORK_ORDERS w
LEFT JOIN WORK_ORDER_CREW_ASSIGMENTS crew
ON CREW.WO_ID = w.ID
INNER JOIN EMPLOYEE_CREWS employeeCrew
ON employeeCrew.CREW_ID = crew.CREW_ID
AND employeeCrew.IS_RESPONSIBLE = 'N'
INNER JOIN EMPLOYEES emp
ON EMP.id = EMPLOYEECREW.EMPLOYEE_ID
WHERE crew.IS_ACTIVE = 'S'
and w.CREATION_DATE between
to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
and to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
查询A: - >执行时间:超过30小时。 - >查询PLan成本:3156361
查询B: - >执行时间:15分钟。 - >查询PLan费用:296107
我认为左连接在两个查询中的工作方式相同,并且它采用相同的数据。如何在时间和成本上产生如此大的差异?
答案 0 :(得分:2)
您正在将苹果与orages进行比较,因为这两个查询不同
- 它们会产生不同的结果。
由于它们不同,所以它们的计划和执行时间不同也不足为奇。
请检查以下简化示例,以了解它们的不同之处:
http://sqlfiddle.com/#!9/93e681/4
CREATE TABLE WORK_ORDERS(
id int
);
INSERT INTO WORK_ORDERS VALUES (1),(2),(3);
CREATE TABLE WORK_ORDER_CREW(
wo_id int,
IS_ACTIVE char(1)
);
INSERT INTO WORK_ORDER_CREW VALUES(1,'Y'),(3,'S');
SELECT *
FROM WORK_ORDERS w
LEFT JOIN WORK_ORDER_CREW crew
ON w.id = crew.wo_id
WHERE crew.IS_ACTIVE = 'S'
;
| id | wo_id | IS_ACTIVE |
|----|-------|-----------|
| 3 | 3 | S |
SELECT *
FROM WORK_ORDERS w
LEFT JOIN (
SELECT * FROM WORK_ORDER_CREW crew
WHERE crew.IS_ACTIVE = 'S'
) crew
ON w.id = crew.wo_id;
| id | wo_id | IS_ACTIVE |
|----|--------|-----------|
| 1 | (null) | (null) |
| 2 | (null) | (null) |
| 3 | 3 | S |
答案 1 :(得分:0)
此时没有任何执行计划,这有点猜测。
我认为问题是LEFT OUTER加入数据范围:
ON (w.id = crewHelpers.wo_id)
AND w.CREATION_DATE BETWEEN to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
AND to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
虽然这在语法上没有任何错误,但它的意思是,不符合日期范围的行被过滤掉,只能由外部联接添加回来。从计划的角度来看,所有过滤都是在post(外部)join之后完成的。
您可以尝试使用以下
ON (w.id = crewHelpers.wo_id)
WHERE w.CREATION_DATE BETWEEN to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
AND to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
可能有必要看看这些结构中哪一个确实给出了正确的结果
答案 2 :(得分:0)
问题解决了。
这是不正确的并且做了很多嵌套循环:
LEFT JOIN (SELECT crew.WO_ID, EMP.DOCUMENT_NUMBER|| '-'|| emp.FIRST_NAME|| ' '|| emp.LAST_NAME helpers
FROM WORK_ORDER_CREW_ASSIGMENTS crew
INNER JOIN EMPLOYEE_CREWS employeeCrew ON employeeCrew.CREW_ID = crew.CREW_ID AND employeeCrew.IS_RESPONSIBLE = 'N'
INNER JOIN EMPLOYEES emp ON EMP.id = EMPLOYEECREW.EMPLOYEE_ID WHERE crew.IS_ACTIVE = 'S'
) crewHelpers ON (w.id = crewHelpers.wo_id)
->**AND**<- w.CREATION_DATE between to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss') and to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')
修复:
LEFT JOIN (SELECT crew.WO_ID, EMP.DOCUMENT_NUMBER|| '-'|| emp.FIRST_NAME|| ' '|| emp.LAST_NAME helpers
FROM WORK_ORDER_CREW_ASSIGMENTS crew
INNER JOIN EMPLOYEE_CREWS employeeCrew ON employeeCrew.CREW_ID = crew.CREW_ID AND employeeCrew.IS_RESPONSIBLE = 'N'
INNER JOIN EMPLOYEES emp ON EMP.id = EMPLOYEECREW.EMPLOYEE_ID WHERE crew.IS_ACTIVE = 'S'
) crewHelpers ON (w.id = crewHelpers.wo_id)
->**WHERE**<- w.CREATION_DATE between to_date('01/01/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss') and to_date('01/04/2016 00:00:00','DD/MM/YYYY HH24:Mi:ss')