Внешнее объединение не работает, в запросе требуются только пустые столбцы - PullRequest
0 голосов
/ 11 октября 2019

Я создал приведенный ниже запрос, чтобы узнать сотрудников, которых нет в таблицах pay_person_pay_methods_f и pay_org_pay_methods_vl, используя условие ORG_PAYMENT_METHOD_NAME - nul l. Я использовал старое внешнее соединение для этого, так как я не знаком с новым, а новое выдает мне ошибки.

Этот запрос ниже дает мне больше данных ... то есть, даже если значения ORG_PAYMENT_METHOD_NAME для них не равны нулю, он выбирается в этом запросе. Что я могу изменить в этом, чтобы получить полное доказательство?

select * from 
(SELECT DISTINCT p.person_number, 
                paaf.assignment_number, 
                payroll_relationship_number, 
                PPPM.percentage, 
                PPPM.priority, 
                POPM.org_payment_method_name, 
                pppm.NAME, 
                To_char(PPPM.effective_start_date, 'DD-MM-YYYY') 
                Effective_start_date, 
                pppm.payment_amount_type, 
                PPPM.amount 
FROM   per_all_people_f p, 
       pay_pay_relationships_dn ppr, 
       pay_person_pay_methods_f pppm, 
       per_all_assignments_m paaf, 
       pay_org_pay_methods_vl POPM 
WHERE  p.person_id = ppr.person_id 
       AND paaf.assignment_type NOT LIKE '%T%' 
       AND paaf.person_id = p.person_id 
      AND PAAF.EFFECTIVE_LATEST_CHANGE = 'Y'
       AND paaf.assignment_status_type LIKE 'ACTIVE%' 
       AND Trunc(sysdate) BETWEEN paaf.effective_start_date AND 
                                  paaf.effective_end_date 
       AND POPM.org_payment_method_id(+) = PPPM.org_payment_method_id
       AND ppr.payroll_relationship_id = pppm.payroll_relationship_id(+)  

       AND Trunc(sysdate) BETWEEN p.effective_start_date AND 
                                  p.effective_end_date 
       AND Trunc(sysdate) BETWEEN ppr.start_date AND ppr.end_date 
      AND Trunc(sysdate) BETWEEN POPM.effective_start_date(+) AND 
                                  POPM.effective_end_date(+) 

       AND Trunc(sysdate) BETWEEN pppm.effective_start_date(+) AND 
                                 pppm.effective_end_date(+)
                                  )
                                  where ORG_PAYMENT_METHOD_NAME is null
                                  order by person_number

Ответы [ 2 ]

0 голосов
/ 12 октября 2019

Наиболее очевидной проблемой является отсутствие (+) в следующей строке:

AND POPM.org_payment_method_id(+) = PPPM.org_payment_method_id

Это должно читаться как

AND POPM.org_payment_method_id(+) = PPPM.org_payment_method_id(+)

, потому что вы пытаетесь (на основедругая информация в запросе) к внешнему объединению в таблице PAY_PERSON_PAY_METHODS_F, а отсутствие завершающего (+) для второго значения в этом сравнении приводит к эффективному преобразованию объединения во внутреннее объединение.

Действительно, вам нужно изучить соединения ANSI "нового стиля". Они были всего лишь 29 лет - я думаю, можно с уверенностью сказать, что они не просто причуда. : -)

Если вы переформатируете запрос, чтобы избавиться от подразумеваемых объединений, вы получите что-то вроде:

SELECT DISTINCT p.PERSON_NUMBER, 
                paaf.ASSIGNMENT_NUMBER, 
                PAYROLL_RELATIONSHIP_NUMBER, 
                pppm.PERCENTAGE, 
                pppm.PRIORITY, 
                popm.ORG_PAYMENT_METHOD_NAME, 
                pppm.NAME, 
                TO_CHAR(pppm.EFFECTIVE_START_DATE, 'DD-MM-YYYY') 
                p.EFFECTIVE_START_DATE, 
                pppm.PAYMENT_AMOUNT_TYPE, 
                pppm.AMOUNT 
  FROM PER_ALL_PEOPLE_F p
  INNER JOIN PAY_PAY_RELATIONSHIPS_DN ppr
    ON ppr.PERSON_ID = p.PERSON_ID AND
       TRUNC(SYSDATE) BETWEEN ppr.START_DATE
                          AND ppr.END_DATE
  INNER JOIN PER_ALL_ASSIGNMENTS_M paaf
    ON paaf.PERSON_ID = p.PERSON_ID AND 
       paaf.EFFECTIVE_LATEST_CHANGE = 'Y' AND
       paaf.ASSIGNMENT_STATUS_TYPE LIKE 'ACTIVE%' AND
       paaf.ASSIGNMENT_TYPE NOT LIKE '%T%' AND
       TRUNC(SYSDATE) BETWEEN paaf.EFFECTIVE_START_DATE 
                          AND paaf.EFFECTIVE_END_DATE 
  LEFT OUTER JOIN PAY_PERSON_PAY_METHODS_F pppm
    ON pppm.PAYROLL_RELATIONSHIP_ID  = ppr.PAYROLL_RELATIONSHIP_ID AND
       TRUNC(SYSDATE) BETWEEN pppm.EFFECTIVE_START_DATE
                          AND pppm.EFFECTIVE_END_DATE
  LEFT OUTER JOIN PAY_ORG_PAY_METHODS_VL popm
    ON popm.ORG_PAYMENT_METHOD_ID = PPPM.ORG_PAYMENT_METHOD_ID AND
       TRUNC(SYSDATE) BETWEEN popm.EFFECTIVE_START_DATE
                          AND popm.EFFECTIVE_END_DATE
  WHERE TRUNC(SYSDATE) BETWEEN p.EFFECTIVE_START_DATE
                           AND p.EFFECTIVE_END_DATE AND
        popm.ORG_PAYMENT_METHOD_NAME IS NULL
  ORDER BY p.PERSON_NUMBER
0 голосов
/ 11 октября 2019

Не проверено:

Я не уверен, что вы хотите, чтобы (+) на POPM и PPPM для ваших системных дат ...

Не означает (+), что все записи, таким образом, делаютэто внешние соединения, которые могут привести к тому, что вы получите больше записей, чем хотелось бы, так как они будут включать все POPM или все записи PPPM, когда на самом деле я думаю, что вы просто хотите все per_all_people?

Вот SQL в новой форме, я считаю...

SELECT * 
FROM (
   SELECT DISTINCT p.person_number, 
                paaf.assignment_number, 
                payroll_relationship_number, 
                PPPM.percentage, 
                PPPM.priority, 
                POPM.org_payment_method_name, 
                pppm.NAME, 
                To_char(PPPM.effective_start_date, 'DD-MM-YYYY') 
                Effective_start_date, 
                pppm.payment_amount_type, 
                PPPM.amount 
  FROM per_all_people_f p
  LEFT JOIN pay_pay_relationships_dn ppr
    on p.person_id = ppr.person_id 
   AND Trunc(sysdate) BETWEEN p.effective_start_date AND p.effective_end_date 
   AND Trunc(sysdate) BETWEEN ppr.start_date AND ppr.end_date 
  LEFT JOIN pay_person_pay_methods_f pppm
    on ppr.payroll_relationship_id = pppm.payroll_relationship_id 
   AND Trunc(sysdate) BETWEEN pppm.effective_start_date AND pppm.effective_end_date

  LEFT JOIN per_all_assignments_m paaf
    ON paaf.person_id = p.person_id  
   AND paaf.assignment_type NOT LIKE '%T%' 
   AND PAAF.EFFECTIVE_LATEST_CHANGE = 'Y'
   AND paaf.assignment_status_type LIKE 'ACTIVE%' 
   AND Trunc(sysdate) BETWEEN paaf.effective_start_date AND paaf.effective_end_date 
  LEFT JOIN pay_org_pay_methods_vl POPM 
   ON POPM.org_payment_method_id = PPPM.org_payment_method_id
  AND Trunc(sysdate) BETWEEN POPM.effective_start_date AND POPM.effective_end_date
)
WHERE ORG_PAYMENT_METHOD_NAME is null
ORDER BY  person_number
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...