简体   繁体   中英

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;

I want all data from employee table so i used left join but i am not getting all rows which is available in employee table some values are missing .Please help me with this . I have 43000 rows in employee but when i am using this i am getting only 17000 rows alone. I am not sure where i am lagging.I want the null column as Master for the right table values.

You can LEFT join all day long, your where clause is still going to function as a filter. Try it with no where clause and see if you get all 43k. Plus you are grouping which could be collapsing rows.

These filters in the WHERE clause turn the OUTER JOIN into an 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

Because they exclude rows where the tested attributes are null (which is what they are in a non-matched outer-joined row).

So there are a couple of approaches. The first is to allow for nulls, eg

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 )

The second is to replace the tables with inline views eg

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

Which approach is the better one for you depends on the data. test them and see.

Think of the data you want in sets. When you LEFT JOIN, you're joining the whole tables when you really only need data from one of them. I've modified a few of your LEFT JOINS to factor for this. Also, doing a WHERE x NOT IN (SELECT x....) can be VERY slow on large datasets. I've changed it to allow the optimizer to work a little better. It now does a LEFT JOIN....WHERE x IS NULL. This should work a lot faster. What do you plan on MAXing? This query is pretty involved. You want to make sure you're getting the initial data that you want before you try to aggregate it.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM