SQL - Oracle에서 일치하는 간격 찾기
테이블이 있습니다.
표:
start end
1 Jan 09 31 Jan 2009
1 Feb 09 28 Feb 2009
1 Mar 09 31 Mar 2009
1 Apr 09 01 May 2009
1 May 09 31 May 2009
1 Jun 09 01 Jul 2009
1 Jul 09 31 Jul 2009
1 Aug 09 31 Aug 2009
1 Sep 09 01 Oct 2009
1 Oct 09 31 Oct 2009
1 Nov 09 01 Dec 2009
1 Dec 09 31 Dec 2009
1 Jan 10 31 Jan 2010
1 Feb 10 03 Mar 2010
1 Mar 10 31 Mar 2010
1 Apr 10 01 May 2010
1 May 10 31 May 2010
1 Jun 10 01 Jul 2010
1 Jul 10 31 Jul 2010
1 Aug 10 31 Aug 2010
1 Sep 10 01 Oct 2010
1 Oct 10 31 Oct 2010
1 Nov 10 01 Dec 2010
1 Dec 10 31 Dec 2010
1 Jan 09 31 Mar 2009
1 Apr 09 30 Jun 2009
1 Jul 09 01 Oct 2009
1 Oct 09 31 Dec 2009
1 Jan 10 31 Mar 2010
1 Apr 10 30 Jun 2010
1 Jul 10 01 Oct 2010
1 Oct 10 31 Dec 2010
1 Jan 09 31 Dec 2009
1 Jan 10 31 Dec 2010
위 내용은 2009년, 2010년 각 월, 분기 및 연도별로 포함되어 있습니다.
다음과 같은 것이 있는 다른 테이블이 있습니다.
테이블2
start end
15-12-09 31-12-09
15-01-12 31-12-13
01-01-11 31-12-13
30-01-98 31-12-13
01-01-98 31-12-13
01-01-98 31-12-13
23-12-12 31-12-13
12-11-11 31-12-13
01-01-10 31-12-13
표 2의 각 항목에 대해 표 1에 포함되는 가능한 시간 프레임을 찾아야 합니다.
표 2의 예, 첫 번째 항목 -
15-12-09 31-12-09
다음에 해당:
1 Dec 09 31 Dec 2009
1 Oct 09 31 Dec 2009
1 Jan 09 31 Dec 2009
Oracle SQL에서 식별이 가능합니까?
먼저 표 1 구간에서 낙하물에 대해 무엇을 의미하는지 정의해야 합니다.
일반적으로 두 가지 해석이 가능합니다.더 제한적인 것은 SubInterval입니다. 즉, 일치된 간격은 기준 간격으로 완전히 덮여 있습니다.
match <---------->
reference <------------------>
두 구간 모두에 공통된 점이 하나 이상 있다는 것을 의미하는 더 완화된 가능성은 교차입니다.
match <---------->
reference <------------------>
그 결정에 따라 다른 가입 조건을 사용하게 됩니다.첫 번째 가능성이 있는 아래 쿼리에서 코멘트를 간단히 바꿔 다른 옵션을 얻습니다.
시뮬레이션된 데이터가 포함된 테이블은 아래에 작성됩니다.
select
tab2.start_d match_start, tab2.end_d match_end,
tab.start_d ref_start, tab.end_d ref_end
from tab2
join tab
-- option SUBINTERVAL
on tab.start_d <= tab2.start_d and tab2.end_d <= tab.end_d
-- option INTERSEC
-- on NOT (tab2.end_d < tab.start_d OR tab2.start_d > tab.end_d)
order by 1,2,3;
SubInterval 옵션에 대한 결과
MATCH_START MATCH_END REF_START REF_END
----------------- ----------------- ----------------- -----------------
15.12.09 00:00:00 31.12.09 00:00:00 01.01.09 00:00:00 31.12.09 00:00:00
15.12.09 00:00:00 31.12.09 00:00:00 01.10.09 00:00:00 31.12.09 00:00:00
15.12.09 00:00:00 31.12.09 00:00:00 01.12.09 00:00:00 31.12.09 00:00:00
INSTRESS 옵션에 대한 레코드를 훨씬 더 많이 얻을 수 있습니다.
여기 검사 데이터가 있습니다.
create table tab as
with tab as (
-- reference intervals
-- months
select add_months(to_date('01012009','ddmmyyyy'),rownum-1) start_d,
add_months(to_date('01012009','ddmmyyyy'),rownum)-1 end_d from dual connect by level <=24
union all
-- quartals
select add_months(to_date('01012009','ddmmyyyy'),3*(rownum-1)) start_d,
add_months(to_date('01012009','ddmmyyyy'),3*rownum)-1 end_d from dual connect by level <=24/3
union all
-- years
select add_months(to_date('01012009','ddmmyyyy'),12*(rownum-1)) start_d,
add_months(to_date('01012009','ddmmyyyy'),12*rownum)-1 end_d from dual connect by level <=24/12
)
select * from tab;
create table tab2 as
with tab2 as (
-- matched intervals
select to_date('15-12-09','dd-mm-rr') start_d, to_date('31-12-09','dd-mm-rr') end_d from dual union all
select to_date('15-01-12','dd-mm-rr') start_d, to_date('31-12-13','dd-mm-rr') end_d from dual union all
select to_date('15-01-98','dd-mm-rr') start_d, to_date('31-12-13','dd-mm-rr') end_d from dual
)
select * from tab2;
간단한 사이가 도움이 될 것입니다.
먼저 두 개의 문장 사이에 있는 문장을 사용하여 table1의 간격 안에 있는 table2의 start_date를 확인하고, table2의 end_date도 table1의 동일한 간격 안에 있는지 확인합니다.두 체크가 동시에 유지되어야 하므로 사용하고 그 사이에 사용해야 합니다.
또한 포괄적인 "사이"가 되는 것은 다음과 같은 방식으로 작동합니다: 첫 번째 매개 변수에 대해 확인합니다.>
아니면=
그리고 두번째 파라미터의 경우.<
아니면=
.
따라서 다음 문장은 동등합니다.
t2.start_date between t1.start_date and t1.end_date
그리고.
t2.start_date >= t1.start_date and t2.start_date <= t1.end_date
찾으려는 SQL은 다음과 같습니다.
select t2.*, '->', t1.* from table2 t2,
table1 t1
where t2.start_date between t1.start_date and t1.end_date
and t2.end_date between t1.start_date and t1.end_date
첫째, 쿼리에서 변환하지 않도록 모든 것을 표준 DATE 형식으로 저장하면 생활이 훨씬 간단해집니다.그러면 패턴은 간단히 다음과 같습니다.
WHERE table2.start <= table1.end
AND table1.start <= table2.end
SQL에서 찾은 구간의 교차점을 표현하는 가장 좋은 방법은 다음과 같습니다.
select *
from table2
join table1
on
table1.start between table2.start and table2.end
or
table2.start between table1.start and table1.end;
교집합의 모든 경우는 다음 두 조건 중 하나에 해당합니다.
뛰어난 성능 없이 아주 간단한 방법을 선택했습니다 =)
with days (dt, max_dt) as
(select (select min(start_dt) from table2) as dt
,(select max(end_dt) from table2) as max_dt
from dual
union all
select dt+1 as dt
,max_dt as max_dt
from days
where dt <max_dt
)
select distinct
t2.start_dt as start_dt2
,t2.end_dt as end_dt2
,t.start_dt as start_dt
,t.end_dt as end_dt
from table2 t2
join days d on (t2.start_dt <=d.dt and t2.end_dt >= d.dt)
join table t on (t.start_dt <=d.dt and t.end_dt >= d.dt)
아래의 경우를 다루려고 합니다.
table interval |---------|
table2 interval |---------------|
table2 interval |----|
table2 interval |--------|
table2 interval |-----|
저는 당신이 여기서 무엇을 이루고 싶은지 잘 모르지만, 이것이 당신에게 도움이 되기를 바랍니다.어떻게든 당신이 언급한 (일부) 결과물을 얻을 수 있었습니다.이 코드를 조금만 수정하면 됩니다.
SELECT CONVERT(VARCHAR(25),CONVERT(DATE,tbl1.START)) 'start',
CONVERT(VARCHAR(25),CONVERT(DATE,tbl1.[END])) 'end',
CONVERT(VARCHAR(25),CONVERT(DATE,tbl2.START)) + ' - ' + CONVERT(VARCHAR(25),CONVERT(DATE,tbl2.[END])) 'table2'
From tbl1, tbl2 where (CONVERT(DATE, tbl2)).START) >= CONVERT (DATE,tbl1).시작) 및 (변환(날짜, tbl2).[END]) <= CONVERT (DATE,tbl1).[END]).
언급URL : https://stackoverflow.com/questions/34184675/find-matching-interval-in-sql-oracle
'code' 카테고리의 다른 글
MAMP에 mysqldump 추가(MacOS X의 MySQL /w Apache PHP) (0) | 2023.10.05 |
---|---|
C 프로그램이 종료하지 않고 코어 덤프를 생성할 수 있는 방법은 무엇입니까? (0) | 2023.10.05 |
Ems란? (Android TextView) (0) | 2023.10.05 |
후속작:여러 데이터베이스 사용 (0) | 2023.10.05 |
Karma가 Chrome에서 작동하도록 하는 방법 (0) | 2023.10.05 |