[英]Joining one table to multiple using LEFT OUTER JOIN ORACLE SQL
SELECT DISTINCT 'DATA' AS DSN,
'MASTER' AS ORG_ID,e.emp_id,
e.emp_name AS EMPLOYEE_NUMBER,
e.emp_firstname AS EMPLOYEE_FIRST_NAME,
e.emp_lastname AS EMPLOYEE_LAST_NAME,
e.emp_val20 AS PAY_STATUS,
(NVL(TO_CHAR(PGT.PAYGRPTYP_NAME),'MASTER')) AS PAY_FREQUENCY,
E.EMP_VAL16 AS PAY_CLASS,
SP.SHFTPAT_NAME AS SHIFT_CODE,
WB.WBU_EMAIL AS EMAIL_ADDR,
(NVL(TO_CHAR( DE.DEPT_NAME),'MASTER')) AS DEPARTMENT,
NULL AS HELD_POSTN,
(NVL(TO_CHAR( J.JOB_NAME),'MASTER')) AS JOB_TITLE,
WB. WBU_NAME AS USER_NAME,
(NVL(TO_CHAR(ET.WBT_ID ),'MASTER')) AS TEAM_CODE,
WT.WBT_NAME AS TEAM_NAME,
WT.WBT_DESC AS TEAM_DESC,
(NVL(TO_CHAR(EB.EMPBDG_BADGE_NUMBER),'MASTER')) AS PERMANENT_BADGE_NO
FROM EMPLOYEE E
LEFT JOIN SHIFT_PATTERN SP
ON E.SHFTPAT_ID =SP.SHFTPAT_ID
LEFT JOIN PAY_GROUP PT
ON E.PAYGRP_ID =PT.PAYGRP_ID
LEFT JOIN PAY_GROUP_TYPE PGT
ON PT.PAYGRPTYP_ID =PGT.PAYGRPTYP_ID
LEFT JOIN EMPLOYEE_BADGE EB
ON E.EMP_ID=EB.EMP_ID
LEFT JOIN EMP_UDF_DATA ED
ON E.EMP_ID=ED.EMP_ID
LEFT JOIN WORKBRAIN_USER WB
ON E.EMP_ID=WB.EMP_ID
LEFT JOIN EMP_DEF_LAB D
ON E.EMP_ID=D.EMP_ID
LEFT JOIN DEPARTMENT DE
ON D.DEPT_ID=DE.DEPT_ID
LEFT JOIN EMPLOYEE_JOB EJ
ON E.EMP_ID=EJ.EMP_ID
LEFT JOIN JOB J
ON EJ.JOB_ID=J.JOB_ID
LEFT JOIN EMPLOYEE_TEAM ET
ON E.EMP_ID=ET.EMP_ID
LEFT JOIN WORKBRAIN_TEAM WT
ON ET.WBT_ID=WT.WBT_ID
LEFT JOIN CALC_GROUP CG
ON E.CALCGRP_ID =CG.CALCGRP_ID
WHERE E.EMP_ID NOT IN (SELECT EMP_ID FROM EMPLOYEE_READER_GROUP)
AND sysdate BETWEEN ET.empt_start_date AND ET.empt_end_date
AND ET.empt_home_team = 'Y'
AND sysdate BETWEEN EJ.EMPJOB_START_DATE AND EJ.EMPJOB_END_DATE
GROUP BY E.EMP_ID,
-- ER.rdrgrp_id,
e.emp_name,
e.emp_lastname,
e.emp_firstname,
e.emp_status,
e.emp_val20,
PGT.PAYGRPTYP_NAME,
E.EMP_VAL16,
e.EMP_VAL18,
EB.EMPBDG_BADGE_NUMBER,
WB.WBU_EMAIL,
DE.DEPT_NAME,
J.JOB_NAME,
SP.SHFTPAT_NAME,
WB. WBU_NAME ,
ET.WBT_ID ,
WT.WBT_NAME,
WT.WBT_DESC;
我想要从employee表中获取所有数据,所以我使用了左联接,但是我没有获取到employee表中所有可用的行,某些值丢失了。请帮助我。 我的员工有43000行,但是当我使用它时,我仅获得17000行。 我不确定我在哪里落后。我想要空列作为Master来获得正确的表值。
您可以整天不停地加入,您的where子句仍将充当过滤器。 尝试使用不带where子句的示例,看看是否能获得全部43k。 另外,您正在分组,这可能会使行崩溃。
WHERE子句中的这些过滤器将OUTER JOIN转换为INNER JOIN:
AND sysdate BETWEEN ET.empt_start_date AND ET.empt_end_date
AND ET.empt_home_team = 'Y'
AND sysdate BETWEEN EJ.EMPJOB_START_DATE AND EJ.EMPJOB_END_DATE
因为它们排除了测试属性为null的行(这是它们在不匹配的外部联接行中的含义)。
因此,有两种方法。 首先是允许空值,例如
AND ( ET.empt_home_team is null or
( sysdate BETWEEN ET.empt_start_date AND ET.empt_end_date
AND ET.empt_home_team = 'Y' )
)
AND ( EJ.EMPJOB_START_DATE is null
or sysdate BETWEEN EJ.EMPJOB_START_DATE AND EJ.EMPJOB_END_DATE )
第二是用内联视图替换表,例如
LEFT JOIN ( select * from EMPLOYEE_TEAM
where sysdate BETWEEN empt_start_date AND empt_end_date
AND empt_home_team = 'Y' ) ET
ON E.EMP_ID=ET.EMP_ID
LEFT JOIN ( select * from EMPLOYEE_JOB
where sysdate BETWEEN EMPJOB_START_DATE AND EMPJOB_END_DATE ) EJ
ON E.EMP_ID=EJ.EMP_ID
哪种方法更适合您取决于数据。 测试他们,看看。
考虑一下您想要的数据集。 当您左联接时,实际上只需要其中之一的数据就可以联接整个表。 我已经修改了一些您的LEFT JOINS来考虑这一点。 同样,在大型数据集上执行WHERE x NOT IN(SELECT x ....)可能非常慢。 我已经对其进行了更改,以使优化器可以更好地工作。 现在,它执行LEFT JOIN .... WHERE x IS NULL。 这应该可以更快地工作。 您对MAXing有什么计划? 这个查询非常复杂。 您想要确保在获取所需的初始数据之前尝试对其进行汇总。
SELECT 'DATA' AS DSN,
'MASTER' AS ORG_ID,e.emp_id,
e.emp_name AS EMPLOYEE_NUMBER,
e.emp_firstname AS EMPLOYEE_FIRST_NAME,
e.emp_lastname AS EMPLOYEE_LAST_NAME,
e.emp_val20 AS PAY_STATUS,
(NVL(TO_CHAR(ptpgt.PAYGRPTYP_NAME),'MASTER')) AS PAY_FREQUENCY, /* From subquery join */
E.EMP_VAL16 AS PAY_CLASS,
SP.SHFTPAT_NAME AS SHIFT_CODE,
WB.WBU_EMAIL AS EMAIL_ADDR,
(NVL(TO_CHAR( DE.DEPT_NAME),'MASTER')) AS DEPARTMENT,
NULL AS HELD_POSTN,
(NVL(TO_CHAR( eej.JOB_NAME),'MASTER')) AS JOB_TITLE, /* From subquery join */
WB. WBU_NAME AS USER_NAME,
(NVL(TO_CHAR(eet.WBT_ID ),'MASTER')) AS TEAM_CODE, /* From subquery join */
WT.WBT_NAME AS TEAM_NAME,
WT.WBT_DESC AS TEAM_DESC,
(NVL(TO_CHAR(EB.EMPBDG_BADGE_NUMBER),'MASTER')) AS PERMANENT_BADGE_NO
FROM EMPLOYEE E
/* This plus WHERE ERG.EMP_ID IS NULL is the same as the subquery filter. But faster. */
LEFT OUTER JOIN EMPLOYEE_READER_GROUP erg ON e.EMP_ID = ERG.EMP_ID
LEFT JOIN SHIFT_PATTERN SP ON E.SHFTPAT_ID =SP.SHFTPAT_ID
LEFT JOIN (
SELECT PT.EMP_ID,PGT.PAYGRPTYP_NAME
FROM PAY_GROUP PT
INNER JOIN PAY_GROUP_TYPE PGT ON PT.PAYGRPTYP_ID =PGT.PAYGRPTYP_ID
) ptpgt ON E.PAYGRP_ID =ptpgt.PAYGRP_ID
LEFT JOIN EMPLOYEE_BADGE EB ON E.EMP_ID=EB.EMP_ID
LEFT JOIN EMP_UDF_DATA ED ON E.EMP_ID=ED.EMP_ID
LEFT JOIN WORKBRAIN_USER WB ON E.EMP_ID=WB.EMP_ID
LEFT JOIN (
SELECT D.EMP_ID, DE.DEPT_NAME
FROM EMP_DEF_LAB D
INNER JOIN DEPARTMENT DE ON D.DEPT_ID=DE.DEPT_ID
) dde ON E.EMP_ID=dde.EMP_ID
LEFT JOIN (
SELECT EJ.EMP_ID, J.JOB_NAME
FROM EMPLOYEE_JOB EJ
INNER JOIN JOB J ON EJ.JOB_ID=J.JOB_ID
WHERE sysdate BETWEEN EJ.EMPJOB_START_DATE AND EJ.EMPJOB_END_DATE
/*
Doublecheck your date filters. Are they getting the edge dates you need?
BETWEEN makes it easy to miss a date, especially if your fields
are DATETIME datatypes.
USE <=/>= to be a bit clearer.
*/
) eej ON E.EMP_ID=eej.EMP_ID
LEFT JOIN (
SELECT ET.EMP_ID, WBT_ID
FROM EMPLOYEE_TEAM ET
INNER JOIN WORKBRAIN_TEAM WT ON ET.WBT_ID=WT.WBT_ID
WHERE
ET.empt_home_team = 'Y'
AND sysdate BETWEEN ET.empt_start_date AND ET.empt_end_date
/*
Doublecheck your date filters. Are they getting the edge dates you need?
BETWEEN makes it easy to miss a date, especially if your fields
are DATETIME datatypes.
USE <=/>= to be a bit clearer.
*/
) eet ON E.EMP_ID=eet.EMP_ID
LEFT JOIN CALC_GROUP CG ON E.CALCGRP_ID=CG.CALCGRP_ID
WHERE
ERG.EMP_ID IS NULL
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.