없는값 추출하기 1 8 491

by rotic [SQL Query] [2021.12.09 08:23:37]


안녕하세요.

근태관리를 구성하는데

한달동안 시간을 체크하지 않은 사람을 추출하고자 하고자 합니다.

간단하게 예시를 들자면,

A테이블       B테이블    
e_date e_idno e_time   e_dept e_idno e_name
20211101 120040013 0650   74 120040013 박동주
120190035 0642   18 120190035 김진석
120140017 0659   72 120140017 남수정
20211102 120190035 0651        
120140017 0632        
20211103 120040013 0652        
120190035 0654        
120140017 0642        
20211104 120140017 0645        
             
결과값            
e_date e_idno e_name        
20211102 120040013 박동주        
20211104 120040013 박동주        
20211104 120190035 김진석        

이렇게 결과값을 받고 싶은데 어떻게 해야 하나요?

고수님들의 조언 부탁드립니다.

 

by 우주민 [2021.12.09 09:23:47]
SELECT T1.e_date, T2.e_idno, T2.e_name
FROM (SELECT DISTINCT e_date FROM A) T1
CROSS JOIN B T2
LEFT OUTER JOIN A T3
ON T1.e_date = T3.e_date
AND T2.e_idno = T3.e_idno
WHERE T3.e_idno IS NULL

 

더 좋은 방법이 있을 듯도 한데...

이정도 밖에 생각이 안나네요.

 

제가 생각한 문제 해결 흐름도는 아래와 같습니다

1. A 테이블의 날짜와 B 테이블을 CROSS JOIN 해서 각 날짜마다 모든 인원이 있는 테이블을 만든다.

2. A 테이블을 위의 테이블에 LEFT OUTER JOIN 시킨다.

3. OUTER JOIN 시킨 테이블의 임의의 컬럼이 NULL 인 데이터만 추출한다.


by 마농 [2021.12.09 10:53:54]

DB 종류 및 버전은 뭔지?
오라클의 경우 PARTITION OUTER JOIN 방식 이용 가능합니다.
그 외의 경우 위 댓글의 방식을 이용하시면 됩니다.
전체 기간 조회인지? 특정기간 조회인지? 도 생각해 보세요.
 

WITH t_user AS
(
SELECT 74 e_dept, '120040013' e_idno, '박동주' e_name FROM dual
UNION ALL SELECT 18, '120190035', '김진석' FROM dual
UNION ALL SELECT 72, '120140017', '남수정' FROM dual
)
, t_data AS
(
SELECT '20211101' e_date, '120040013' e_idno, '0650' e_time FROM dual
UNION ALL SELECT '20211101', '120190035', '0642' FROM dual
UNION ALL SELECT '20211101', '120140017', '0659' FROM dual
UNION ALL SELECT '20211102', '120190035', '0651' FROM dual
UNION ALL SELECT '20211102', '120140017', '0632' FROM dual
UNION ALL SELECT '20211103', '120040013', '0652' FROM dual
UNION ALL SELECT '20211103', '120190035', '0654' FROM dual
UNION ALL SELECT '20211103', '120140017', '0642' FROM dual
UNION ALL SELECT '20211104', '120140017', '0645' FROM dual
)
SELECT a.e_date
     , b.e_idno
     , b.e_name
  FROM t_user b
  LEFT OUTER JOIN
       (SELECT *
          FROM t_data
         WHERE e_date BETWEEN '20211101' AND '20211104'
        ) a
 PARTITION BY (a.e_date)
    ON a.e_idno = b.e_idno
 WHERE a.e_idno IS NULL
;

 


by 동동동 [2021.12.09 11:07:19]

마농님 혹시 해당 건은 ansi쿼리로만 가능한 건가요?


by 마농 [2021.12.09 11:16:18]

일단 LEFT OUTER JOIN 구문에서만 PARTITION BY 를 붙일 수 있습니다.
(+) 를 이용한 오리클 전통 방식에서는 이러한 구문이 없습니다.
다만, 오라클에서만 되는 구문을 ANSI 라 할 수 있는지 모르겠네요?


by 동동동 [2021.12.09 11:50:06]

답글 감사드립니다..


by rotic [2021.12.09 12:49:02]

오라클 사용하는데

PARTITION OUTER JOIN에 대해서 공부하는 계기가 되었네요.

답변 감사합니다.

수고하세요.


by 우주민 [2021.12.09 13:23:46]

PARTITION 별로 JOIN 하는 기능이 있는지 찾아봤었는데...

ANSI 에서는 없었군요... 어쩐지... 흠...

오라클 한정 이라지만 새로운 방법 잘 배웠습니다.


by JohnSnow [2021.12.10 13:03:55]

(Oralce 예)

 

SELECT A.e_date, B.e_idno, B.e_name

  FROM B테이블 B, A테이블 A

 WHERE B.e_idno = A.e_idno(+)

     AND B.e_idno NOT IN (

                SELECT e_idno FROM B테이블 BB

                 WHERE A,e_idno = BB.e_idno

                    AND A.e_date between to_char(SYSDATE,'YYYYMMDD')

                                            and to_char(ad_months(SYSDATE,-1),'YYYYMMDD')

               );

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입