기간 비교
MySQL에서 날짜 범위 목록 (범위 시작 및 범위 끝)이있는 경우. 예 :
10/06/1983 to 14/06/1983
15/07/1983 to 16/07/1983
18/07/1983 to 18/07/1983
그리고 다른 날짜 범위에 이미 목록에있는 범위 중 하나가 포함되어 있는지 확인하고 싶습니다. 어떻게?
예 :
06/06/1983 to 18/06/1983 = IN LIST
10/06/1983 to 11/06/1983 = IN LIST
14/07/1983 to 14/07/1983 = NOT IN LIST
이것은 고전적인 문제이며 논리를 바꾸면 실제로 더 소유합니다.
예를 들어 보겠습니다.
여기에 한 기간을 게시하고 어떤 방식으로 겹치는 다른 기간의 모든 변형을 게시합니다.
|-------------------| compare to this one
|---------| contained within
|----------| contained within, equal start
|-----------| contained within, equal end
|-------------------| contained within, equal start+end
|------------| not fully contained, overlaps start
|---------------| not fully contained, overlaps end
|-------------------------| overlaps start, bigger
|-----------------------| overlaps end, bigger
|------------------------------| overlaps entire period
반면에 겹치지 않는 게시물을 게시하겠습니다.
|-------------------| compare to this one
|---| ends before
|---| starts after
간단한 비교를하면 다음과 가변됩니다.
starts after end
ends before start
그런 다음 겹치지 않는 모든 것을 다음 일치하지 않는 모든 기간을 찾으십시오.
최종 NOT IN LIST 예제의 경우이 두 규칙과 일치 함을 알 수 있습니다.
다음 기간이 범위를 벗어나지 않는지 결정해야합니다.
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
테이블에 range_end 및 range_start라는 열이 있으면 일치하는 모든 행을 검색하는 간단한 SQL이 있습니다.
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
거기에 NOT 을 유의하십시오 . 개의 간단한 규칙 두이 일치 여부하지 않는 모든 행을 발견 하므로 간단한 NOT를 반대로 바꿔서 은이 일치 여부 하지 않는 행 중 하나가 아닌 경우 일치 여부하는 행 중 하나 여야합니다 .
NOT을 제거하기 위해 간단한 반전 논리를 적용하면 다음과 같이 끝납니다.
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start
1983 년 6 월 6 일 ~ 1983 년 6 월 18 일의 예제 범위를 취하고 범위에 대해 시작 및 종료 라는 열이에서 가정하면 다음 과 같은 절을 사용할 수 있습니다.
where ('1983-06-06' <= end) and ('1983-06-18' >= start)
즉, 테스트 범위의 시작이 데이터베이스 범위의 끝 이전이고 테스트 범위의 끝이 데이터베이스 범위의 시작 또는 이후에 있는지 확인하십시오.
RDBMS가 OVERLAP () 함수를 지원하는 경우 이는 사소 해집니다. 자체 솔루션이 필요하지 않습니다. (오라클에서는 작동하지만 문서화되지 않았습니다).
예상되는 결과에서
1983 년 6 월 6 일 ~ 1983 년 6 월 18 일 = 목록에 있음
그러나이 기간은 기간 표 (목록이 아님)에있는 기간을 포함하거나 포함하지 않습니다. 그러나 기간은 1983 년 10 월 6 일부터 1983 년 6 월 14 일까지입니다.
Snodgrass 책 ( http://www.cs.arizona.edu/people/rts/tdbbook.pdf )이 유용 할 수 있습니다.이 책 은 mysql보다 이전 버전이지만 시간 개념은 변경되지 않았습니다 ;-)
이 문제를 MySQL에서 처리하는 함수를 만들었습니다. 사용하기 전에 날짜를 초로 변환하십시오.
DELIMITER ;;
CREATE FUNCTION overlap_interval(x INT,y INT,a INT,b INT)
RETURNS INTEGER DETERMINISTIC
BEGIN
DECLARE
overlap_amount INTEGER;
IF (((x <= a) AND (a < y)) OR ((x < b) AND (b <= y)) OR (a < x AND y < b)) THEN
IF (x < a) THEN
IF (y < b) THEN
SET overlap_amount = y - a;
ELSE
SET overlap_amount = b - a;
END IF;
ELSE
IF (y < b) THEN
SET overlap_amount = y - x;
ELSE
SET overlap_amount = b - x;
END IF;
END IF;
ELSE
SET overlap_amount = 0;
END IF;
RETURN overlap_amount;
END ;;
DELIMITER ;
다음 예를 살펴보십시오. 당신에게 도움이 될 것입니다.
SELECT DISTINCT RelatedTo,CAST(NotificationContent as nvarchar(max)) as NotificationContent,
ID,
Url,
NotificationPrefix,
NotificationDate
FROM NotificationMaster as nfm
inner join NotificationSettingsSubscriptionLog as nfl on nfm.NotificationDate between nfl.LastSubscribedDate and isnull(nfl.LastUnSubscribedDate,GETDATE())
where ID not in(SELECT NotificationID from removednotificationsmaster where Userid=@userid) and nfl.UserId = @userid and nfl.RelatedSettingColumn = RelatedTo
MS SQL에서 시도
WITH date_range (calc_date) AS (
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, [ending date]) - DATEDIFF(DAY, [start date], [ending date]), 0)
UNION ALL SELECT DATEADD(DAY, 1, calc_date)
FROM date_range
WHERE DATEADD(DAY, 1, calc_date) <= [ending date])
SELECT P.[fieldstartdate], P.[fieldenddate]
FROM date_range R JOIN [yourBaseTable] P on Convert(date, R.calc_date) BETWEEN convert(date, P.[fieldstartdate]) and convert(date, P.[fieldenddate])
GROUP BY P.[fieldstartdate], P.[fieldenddate];
CREATE FUNCTION overlap_date(s DATE, e DATE, a DATE, b DATE)
RETURNS BOOLEAN DETERMINISTIC
RETURN s BETWEEN a AND b or e BETWEEN a and b or a BETWEEN s and e;
BETWEEN SQL 문을 사용하는 또 다른 방법
포함 된 기간 :
SELECT *
FROM periods
WHERE @check_period_start BETWEEN range_start AND range_end
AND @check_period_end BETWEEN range_start AND range_end
제외 기간 :
SELECT *
FROM periods
WHERE (@check_period_start NOT BETWEEN range_start AND range_end
OR @check_period_end NOT BETWEEN range_start AND range_end)
SELECT *
FROM tabla a
WHERE ( @Fini <= a.dFechaFin AND @Ffin >= a.dFechaIni )
AND ( (@Fini >= a.dFechaIni AND @Ffin <= a.dFechaFin) OR (@Fini >= a.dFechaIni AND @Ffin >= a.dFechaFin) OR (a.dFechaIni>=@Fini AND a.dFechaFin <=@Ffin) OR
(a.dFechaIni>=@Fini AND a.dFechaFin >=@Ffin) )
참고 URL : https://stackoverflow.com/questions/143552/comparing-date-ranges
'IT' 카테고리의 다른 글
우분투 16.04에서 nodejs 업데이트 (0) | 2020.07.28 |
---|---|
드롭 다운 protractorjs e2e 테스트에서 옵션을 선택하는 방법 (0) | 2020.07.28 |
사용자가 모든 그룹을 얻는 방법은 무엇입니까? (0) | 2020.07.28 |
제목을 8 방향으로 분류 할 때 체인이 if / else if 경우를 피하는 방법은 무엇입니까? (0) | 2020.07.28 |
점이 선의 오른쪽인지 (0) | 2020.07.28 |