[SQL] 연속 날짜를 감지하는 것은 SQL을 사용하여 범위
SQL연속 날짜를 감지하는 것은 SQL을 사용하여 범위
나는 시작과 끝 날짜 정보를 필요로 달력 개체를 채우려. 나는 날짜의 순서를 포함하는 하나의 열을 가지고있다. 날짜 중 일부는 연속입니다 (하루 차이가) 일부는 아니다.
InfoDate
2013-12-04 consecutive date [StartDate]
2013-12-05 consecutive date
2013-12-06 consecutive date [EndDate]
2013-12-09 [startDate]
2013-12-10 [EndDate]
2014-01-01 [startDate]
2014-01-02
2014-01-03 [EndDate]
2014-01-06 [startDate]
2014-01-07 [EndDate]
2014-01-29 [startDate]
2014-01-30
2014-01-31 [EndDate]
2014-02-03 [startDate]
2014-02-04 [EndDate]
나는 각각의 연속 날짜의 시작 및 종료 날짜 (첫 번째와 블록의 마지막 한) 범위를 선택하고 싶다.
StartDate EndDate
2013-12-04 2013-12-06
2013-12-09 2013-12-10
2014-01-01 2014-01-03
2014-01-06 2014-01-07
2014-01-29 2014-01-31
2014-02-03 2014-02-04
난 단지 SQL을 사용하여 문제를 해결합니다.
해결법
-
==============================
1.아니 조인 또는 재귀 CTE는 필요. 즉 연속하는 시퀀스 내의 불변이기 때문에 표준 틈새 및 섬 용액 (마이너스 값 ROW_NUMBER)가 그룹이다. 시작 및 종료 날짜는 그룹의 MIN () 및 MAX ()입니다.
아니 조인 또는 재귀 CTE는 필요. 즉 연속하는 시퀀스 내의 불변이기 때문에 표준 틈새 및 섬 용액 (마이너스 값 ROW_NUMBER)가 그룹이다. 시작 및 종료 날짜는 그룹의 MIN () 및 MAX ()입니다.
WITH t AS ( SELECT InfoDate d,ROW_NUMBER() OVER(ORDER BY InfoDate) i FROM @d GROUP BY InfoDate ) SELECT MIN(d),MAX(d) FROM t GROUP BY DATEDIFF(day,i,d)
-
==============================
2.여기 요 ..
여기 요 ..
;WITH CTEDATES AS ( SELECT ROW_NUMBER() OVER (ORDER BY Infodate asc ) AS ROWNUMBER,infodate FROM YourTableName ), CTEDATES1 AS ( SELECT ROWNUMBER, infodate, 1 as groupid FROM CTEDATES WHERE ROWNUMBER=1 UNION ALL SELECT a.ROWNUMBER, a.infodate,case datediff(d, b.infodate,a.infodate) when 1 then b.groupid else b.groupid+1 end as gap FROM CTEDATES A INNER JOIN CTEDATES1 B ON A.ROWNUMBER-1 = B.ROWNUMBER ) select min(mydate) as startdate, max(infodate) as enddate from CTEDATES1 group by groupid
이 질문에 대답하는 경우, 대답으로 표시하는 것을 잊지 마십시오.
-
==============================
3.나는 #consec 전화 후 다음을 perforemed 테이블에 이러한 값을 삽입했습니다 :
나는 #consec 전화 후 다음을 perforemed 테이블에 이러한 값을 삽입했습니다 :
select t1.* ,t2.infodate as binfod into #temp1 from #consec t1 left join #consec t2 on dateadd(DAY,1,t1.infodate)=t2.infodate select t1.* ,t2.infodate as binfod into #temp2 from #consec t1 left join #consec t2 on dateadd(DAY,1,t2.infodate)=t1.infodate ;with cte as( select infodate, ROW_NUMBER() over(order by infodate asc) as seq from #temp1 where binfod is null ), cte2 as( select infodate, ROW_NUMBER() over(order by infodate asc) as seq from #temp2 where binfod is null ) select t2.infodate as [start_date] ,t1.infodate as [end_date] from cte t1 left join cte2 t2 on t1.seq=t2.seq
언제 까지나 당신의 날짜 기간이 중복되지 않기 때문에, 그것은 당신을 위해 일을해야한다.
-
==============================
4.여기에는 테스트 데이터 내 샘플입니다 :
여기에는 테스트 데이터 내 샘플입니다 :
--required output -- 01 - 03 -- 08 - 09 -- 12 - 14 DECLARE @maxRN int; WITH #tmp AS ( SELECT CAST('2013-01-01' AS date) DT UNION ALL SELECT CAST('2013-01-02' AS date) UNION ALL SELECT CAST('2013-01-03' AS date) UNION ALL SELECT CAST('2013-01-05' AS date) UNION ALL SELECT CAST('2013-01-08' AS date) UNION ALL SELECT CAST('2013-01-09' AS date) UNION ALL SELECT CAST('2013-01-12' AS date) UNION ALL SELECT CAST('2013-01-13' AS date) UNION ALL SELECT CAST('2013-01-14' AS date) ), #numbered AS ( SELECT 0 RN, CAST('1900-01-01' AS date) DT UNION ALL SELECT ROW_NUMBER() OVER (ORDER BY DT) RN, DT FROM #tmp ) SELECT * INTO #tmpTable FROM #numbered; SELECT @maxRN = MAX(RN) FROM #tmpTable; INSERT INTO #tmpTable SELECT @maxRN + 1, CAST('2100-01-01' AS date); WITH #paired AS ( SELECT ROW_NUMBER() OVER(ORDER BY TStart.DT) RN, TStart.DT DTS, TEnd.DT DTE FROM #tmpTable TStart INNER JOIN #tmpTable TEnd ON TStart.RN = TEnd.RN - 1 AND DATEDIFF(dd,TStart.DT,TEnd.DT) > 1 ) SELECT TS.DTE, TE.DTs FROM #paired TS INNER JOIN #paired TE ON TS.RN = TE.RN -1 AND TS.DTE <> TE.DTs -- you could remove this filter if you want to have start and end on the same date DROP TABLE #tmpTable
실제 테이블과 #tmp 데이터를 교체합니다.
-
==============================
5.이 좋아해요 여기에 sqlfiddle입니다 수 있습니다
이 좋아해요 여기에 sqlfiddle입니다 수 있습니다
select min(ndate) as start_date, max(ndate) as end_date from (select ndate, dateadd(day, -row_number() over (order by ndate), ndate) as rnk from dates ) t group by rnk
-
==============================
6.
SELECT InfoDate , CASE WHEN TRUNC(InfoDate - 1) = TRUNC(lag(InfoDate,1,InfoDate) over (order by InfoDate)) THEN NULL ELSE InfoDate END STARTDATE, CASE WHEN TRUNC(InfoDate + 1) = TRUNC(lead(InfoDate,1,InfoDate) over (order by InfoDate)) THEN NULL ELSE InfoDate END ENDDATE FROM TABLE;
from https://stackoverflow.com/questions/20402089/detect-consecutive-dates-ranges-using-sql by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 테이블 오라클의 마지막 행을 얻는 방법 (0) | 2020.04.25 |
---|---|
[SQL] 그것은 하나의 UPDATE SQL 문으로 여러 업데이트를 수행 할 수 있습니까? (0) | 2020.04.25 |
[SQL] CASE 대 디코드 (0) | 2020.04.25 |
[SQL] 그룹화 MySQL의 데이터에서 최신 날짜를 가져옵니다 (0) | 2020.04.25 |
[SQL] SQL 동적 열 이름을 생성하는? (0) | 2020.04.25 |