by 열공합시다 [2023.02.08 11:26:52]
24가 나오길 바라고 만든 쿼리이긴한데
만들고나서보니 2345가 조회되겠다 싶었습니다.
근디 24로 잘 조회되더라구요.
그동안 exists 나 in으로만 서브쿼리조건을 걸어와서 그런지 저 조건이 메인에도 영향이 가는거라 생각을 못하고 있었어요
이게 맞는건가요?....
갑자기 멘탈이 나가네요 ㅜㅜ
SELECT A.RN, A.CS_PK,
(SELECT MIN(B.RN)
FROM MAIN_DB B
WHERE B.CS_PK = A.CS_PK) CK
FROM MAIN_DB A
ORDER BY RN
;
위 쿼리를 수행하면 아래와 같은 결과를 얻을 수 있습니다.
RN CS_PK CK
1 A 1
2 A 1
3 B 3
4 B 3
5 C 5
RN 기준으로 1일때 서브쿼리의 값이 1이므로 본문의 WHERE 조건을 만족 못합니다.
같은 방식으로 서브 쿼리를 만족 하는 데이터는 RN이 2, 4만 됩니다.
해당 결과는 하나의 로우씩 처리 된다고 생각하시면 이해가 쉬우실 겁니다.
연관/비연관 서브쿼리
- 비연관 서브쿼리 : 서브쿼리 안에 메인쿼리 조건이 없어 독립적으로 수행됨. 수행 결과를 메인에 제공(제공자)
- 연관 서브쿼리 : 서브쿼리 안에 메인쿼리 조건이 있어 메인쿼리에 종속적으로 수행됨. 메인 각 행마다 서브쿼리 수행 결과 확인(확인자)
즉, 질문의 서브쿼리는 연관서브쿼리인데 결과가 1 하나만 나올거라고 착각하신 것 같습니다.
메인 쿼리 5행에 대해 서브쿼리가 5번 각각 수행됩니다.
그럼 중복건을 찾는 더 깔끔한 방법이 있을까요
전 row number로 파티션바이로 순번매기는거밖에 생각을 못하고 있었거든여
그냥 중복을 찾는게 아닌 것 같은데요?
중복 건 중에 최초값 하나를 제외한 나머지 대상을 찾는 것 같은데요?
우리말은 아 다르고 어 다르기 때문에 정확하게 표현해 주셔야 합니다.
1. 위와 같이 서브쿼리 조건을 이용할 수도 있고
2. 인라인뷰로 조인해서 할 수도 있구요.
3. 순위 분석함수를 이용해 뽑을 수도 있습니다.
3번 방식이 그나마 깔끔해 보입니다.
넵넵 맞습니당 중복값중에 최초값을 제외한 나머지를 찾아서 삭제하려고했습니다.
순위분석으로 최초를 1로 잡아서 1보다 큰거를 찾는식으로 하는걸 생각했는데 그게 말씀해주신 3번이죠? 그게 제일 나아서 다행이긴하네요..
아직도 연관서브쿼리가 의아하긴한데 그냥 외워야죵모.. ㅜ
제가 여태 이해하고있던건
5번 도는건 맞지만 그 중 하나에 min보다 큰 게 2345가 있기 때문에 2345가 나오는걸로 이해하고 있었는데.. 후 왜 여태 그렇게 생각하고 있었을까...
1. 그냥 단순 조회용이라면? 테이블을 한번만 사용하는 row_number 방식이 좋지만.
- 삭제용이라면? row_number 의 결과를 다시 원본테이블과 조인 걸어야 하므로, 결국 테이블 또 사용.
- 차라리 1 번 방식이 나을 수 도 있습니다.
2. 외우시면 계속 헷갈립니다.
- 이해하시길 바래요.
이해하려고 계속 돌려보고 있습니당 ㅜㅜ
연관서브쿼리는 결국 셀렉트절에 파티션바이겉은 개념이라고 생각하면 되는거같은데 맞나요?
파티션바이도 파티션바이안에 있는 조건내에서 함수를 수행하는거니까
연관서브쿼리에 조건걸린 컬럼은 연관서브쿼리에 걸려있는 조건 내에서만 비교한다.
이렇게 이해해도 무방하겠죠?
연관서브쿼리는 결국 셀렉트절에 파티션바이겉은 개념이라고 생각하면 되는거같은데 맞나요?
- 너무 복잡하게 생각하는 것 같은데요? 오히려 이상합니다.
- 그냥 메인 쿼리 결과 각각의 행마다 서브쿼리가 개별 수행되어 결과가 나온다 라고 생각하면 될 것 같습니다.
- 맨 첫번째 창조의날개님 답글의 쿼리를 이용해 서브쿼리 결과를 확인하시면 이해하는데 도움이 될 것입니다.
- 메인 5행에 대한 서브쿼리 결과도 5개
아... 그렇군요..
처음 답변주셨던게 제일 정리가 잘 되었던거네요..
아공 감사합니다