簡體   English   中英

使用LEFT OUTER JOIN ORACLE SQL將一個表連接到多個表

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM