복붙노트

[SQL] 날짜 범위를 비교

SQL

날짜 범위를 비교

MySQL의에서, 나는 날짜 범위 (범위 시작 및 범위 엔드)의 목록이있는 경우. 예를 들면

10/06/1983 to 14/06/1983
15/07/1983 to 16/07/1983
18/07/1983 to 18/07/1983

그리고 나는 그렇게 할 것입니다 방법, 다른 날짜 범위가 이미 목록의 범위 중 하나를 포함하는 경우 확인하려면?

EG

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

해결법

  1. ==============================

    1.이것은 고전적인 문제이며, 당신이 논리를 반대로하면 실제로 쉽다.

    이것은 고전적인 문제이며, 당신이 논리를 반대로하면 실제로 쉽다.

    한 가지 예를 들어 보겠습니다.

    여기 시간의 한주기를 게시하고, 어떤 방법으로 중복 다른 기간의 모든 다른 유사합니다.

               |-------------------|          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 제거하는 당신은 될 겁니다 :

    SELECT *
    FROM periods
    WHERE range_start <= @check_period_end
          AND range_end >= @check_period_start
    
  2. ==============================

    2.18/06/1983에 1983년 6월 6일의 귀하의 예제 범위를 촬영하고 열이 범위에 대한 시작과 끝을 불렀다 가정,이 같은 절을 사용할 수 있습니다

    18/06/1983에 1983년 6월 6일의 귀하의 예제 범위를 촬영하고 열이 범위에 대한 시작과 끝을 불렀다 가정,이 같은 절을 사용할 수 있습니다

    where ('1983-06-06' <= end) and ('1983-06-18' >= start)
    

    테스트 범위의 시작을 확인 즉하면 데이터베이스 범위가 끝나기 전에, 그리고 테스트 범위의 끝은 후 또는 데이터베이스 범위의 시작에 있는지.

  3. ==============================

    3.당신의 RDBMS가 오버랩 () 함수를 지원하는 경우 다음이 사소한된다 없습니다 - 자체 개발 한 솔루션이 필요합니다. (오라클 그것은 Apparantly 히 작동하지만 문서화되지 않은).

    당신의 RDBMS가 오버랩 () 함수를 지원하는 경우 다음이 사소한된다 없습니다 - 자체 개발 한 솔루션이 필요합니다. (오라클 그것은 Apparantly 히 작동하지만 문서화되지 않은).

  4. ==============================

    4.당신의 예상 결과에서는 말

    당신의 예상 결과에서는 말

    목록 1983년 6월 6일 18/06/1983에 =

    그러나이 기간은 포함되어 있지 않으며 기간의 테이블 (안 목록!)의 기간 중 하나로 포함되어 있습니다. 그것은, 그러나, 14/06/1983에 기간을 1983년 10월 6일 중복 않습니다.

    그것은 사전에 날짜 MySQL을하지만, 시간의 개념은 변경되지 않았습니다 ;-) : 당신은 (http://www.cs.arizona.edu/people/rts/tdbbook.pdf) 유용 노드 그래스 책을 찾을 수 있습니다

  5. ==============================

    5.나는 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 ;
    
  6. ==============================

    6.다음의 예에 봐. 그것은 당신을 위해 도움이되는 것입니다.

    다음의 예에 봐. 그것은 당신을 위해 도움이되는 것입니다.

        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
    
  7. ==============================

    7.MS SQL에이 시도

    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];
    
  8. ==============================

    8.

    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;
    
  9. ==============================

    9.SQL 문을 BETWEEN 사용하여 또 다른 방법

    SQL 문을 BETWEEN 사용하여 또 다른 방법

    기간 포함 :

    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)
    
  10. ==============================

    10.

    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) )
    
  11. from https://stackoverflow.com/questions/143552/comparing-date-ranges by cc-by-sa and MIT license