쿼리질문입니다. 0 10 1,394

by 제임스 [SQL Query] [2014.08.22 11:04:04]


아래와같이 시작숫자와 종료숫자가 있는데요.

각 행들이 서로 종속적으로   start1 와 end1  숫자 범위내에 포함되어있는 데이타를 추출하는 쿼리가 필요합니다.

예를들면  start1  는 start1 와 end1  숫자 범위내에 포함되어있어야하고요,

또는 end1  도 start1 와 end1  범위내에 포함되어있으면 출력입니다.

예상결과는 맨밑에 있습니다.

쿼리를 어떻게 변형해야 할까요?

 

 

with  w_ip as

(

               select '010'  start1, '200'   end1 from dual

union all   select '011' start1, '015' end1 from dual

union all select '003' start1, '050' end1 from dual

union all select '080' start1, '255' end1 from dual

union all select '201' start1, '255' end1 from dual

union all select '001' start1, '002' end1 from dual

)

select *

from w_ip

 

-- 결과

start1      end1

----------------------------

 '010'       '200'

 '011'       '015'

 '003'       '050'

 '080'       '255'

 

 

by 우리집아찌 [2014.08.22 11:20:24]

MAX() OVER( ( ORDER BY ..) , MIN() OVER( ORDER BY ..)

만든다음 LAG() OVER() 쓰시면 될듯한데요..

 

 


by 마농 [2014.08.22 11:20:49]

결과에 대한 설명을 해주세요.

왜? 4개는 포함되고, 2개는 제외되는지?


by 제임스 [2014.08.22 11:31:35]

전체 6개의 행중에서 4개만 출력된 이유는 서로 간의 시작숫자 및 종료숫자를 보면

서로 종속적으로 해당범위내에 포함이 되어잇습니다.

'010' '200' ==> 종료숫자인 200 이 '080' start1, '255' 사이에 포함되어있음

'011' '015' ==> 시작숫자 및 종료숫자가 '003' start1, '050' 사이에 포함되어잇음

'003' '050' ===> 종료숫자인 '050'이 '010' start1, '200' 사이에 포함되어있음

'080' '255' ==> 종료숫자인 '255'가 '201' start1, '255' 사이에 포함되어잇음

 

====

출력이 안된 '201' start1, '255'

'001' start1, '002'

는 어느 숫자 그룹에도 포함이 되지않아 출력이 안되는구조임


by 마농 [2014.08.22 11:39:16]

(080, 255) 가 (201, 255) 에 포함되는데
(201, 255) 는 (080, 255) 에 포함되지 않는 이유가???


by 제임스 [2014.08.22 12:33:24]

아.. 그것도 포함되네요. 제가 잘못봣습니다. 그것도 출력맞아요..^^


by 비주류 [2014.08.22 13:04:05]
-- 성능은 안좋겠지만 생각난대로 적어봅니다.
select * from w_ip a
where exists (
    select 1 from w_ip b
    where a.rowid <> b.rowid
    and   (a.start1 between b.start1 and b.end1
           or a.end1 between b.start1 and b.end1)
)

 


by 마농 [2014.08.22 14:08:21]
구간 중복 검색시 흔히 저지르게 되는 오류입니다.
AND (a.s BETWEEN b.s AND b.e OR a.e BETWEEN b.s AND b.e)
이렇게 하면...
B 를 기준으로 A 의 6가지 케이스별로 중복 체크를 해보면
B0 :         s-----------e
A1 : s-----e
A2 :                       s-----e
A3 :      s-----e
A4 :            s-----e
A5 :                  s-----e
A6 : s----------------------------e
1, 2 는 중복이 안되구요
3,4,5,6 모두 중복이지만 위와 같은 조건으로는 6번이 누락이 됩니다.
AND a.s < b.e
AND a.e > b.s
이렇게 하시면 간결한 구문으로 모두 체크가 됩니다.
부등호에 이퀄(=)을 붙일지 안붙일지는 그때 상황에 맞게 판단하면 됩니다.

 


by 비주류 [2014.08.22 15:52:52]

[각 행들이 서로 종속적으로 start1 과 end1 숫자 범위내에 포함되어있는 데이타를 추출]
"예를들면  start1  는 start1 와 end1  숫자 범위내에 포함되어있어야하고요, 또는 end1  도 start1 와 end1  범위내에 포함되어있으면 출력입니다."
이 부분 그대로 옮기다 보니 쿼리가 그렇게 되었네요.

요건이 "구간 중복" 체크 건이라면, 아래 답변 달아주신 내용이 정확합니다.
(질문자는 아니지만) 이해하기 쉽게 좋은 답변 달아주셔서 항상 잘 참고하고 있습니다. 감사합니다.


by 마농 [2014.08.22 13:42:50]
WITH w_ip AS
(
SELECT 1 pk, '010' start1, '200' end1 FROM dual
UNION ALL SELECT 2, '011', '015' FROM dual
UNION ALL SELECT 3, '003', '050' FROM dual
UNION ALL SELECT 4, '080', '255' FROM dual
UNION ALL SELECT 5, '201', '255' FROM dual
UNION ALL SELECT 6, '001', '002' FROM dual
)
-- 0. 구간 중복 체크는 시작과 종료를 서로 교차비교하면 됩니다.
-- 1. Self Join 후 중복 제거
SELECT DISTINCT a.pk, a.start1, a.end1
  FROM w_ip a
     , w_ip b
 WHERE b.pk    != a.pk
   AND b.start1 < a.end1
   AND b.end1   > a.start1
;
-- 2. Exists 체크
SELECT *
  FROM w_ip a
 WHERE EXISTS (SELECT 1
                 FROM w_ip b
                WHERE b.pk    != a.pk
                  AND b.start1 < a.end1
                  AND b.end1   > a.start1
               )
;

 


by 제임스 [2014.08.22 16:48:56]

감사합니다. ^^

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