Comparing date ranges

后端 未结 10 1353
予麋鹿
予麋鹿 2020-11-22 16:10

In MySQL, If I have a list of date ranges (range-start and range-end). e.g.

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


        
相关标签:
10条回答
  • 2020-11-22 16:11
    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) )
    
    0 讨论(0)
  • 2020-11-22 16:13

    This is a classical problem, and it's actually easier if you reverse the logic.

    Let me give you an example.

    I'll post one period of time here, and all the different variations of other periods that overlap in some way.

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

    on the other hand, let me post all those that doesn't overlap:

               |-------------------|          compare to this one
         |---|                                ends before
                                     |---|    starts after
    

    So if you simple reduce the comparison to:

    starts after end
    ends before start
    

    then you'll find all those that doesn't overlap, and then you'll find all the non-matching periods.

    For your final NOT IN LIST example, you can see that it matches those two rules.

    You will need to decide wether the following periods are IN or OUTSIDE your ranges:

               |-------------|
       |-------|                       equal end with start of comparison period
                             |-----|   equal start with end of comparison period
    

    If your table has columns called range_end and range_start, here's some simple SQL to retrieve all the matching rows:

    SELECT *
    FROM periods
    WHERE NOT (range_start > @check_period_end
               OR range_end < @check_period_start)
    

    Note the NOT in there. Since the two simple rules finds all the non-matching rows, a simple NOT will reverse it to say: if it's not one of the non-matching rows, it has to be one of the matching ones.

    Applying simple reversal logic here to get rid of the NOT and you'll end up with:

    SELECT *
    FROM periods
    WHERE range_start <= @check_period_end
          AND range_end >= @check_period_start
    
    0 讨论(0)
  • 2020-11-22 16:14

    Another method by using BETWEEN sql statement

    Periods included :

    SELECT *
    FROM periods
    WHERE @check_period_start BETWEEN range_start AND range_end
      AND @check_period_end BETWEEN range_start AND range_end
    

    Periods excluded :

    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)
    
    0 讨论(0)
  • 2020-11-22 16:15

    Try This on 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];
    
    0 讨论(0)
  • 2020-11-22 16:16

    Taking your example range of 06/06/1983 to 18/06/1983 and assuming you have columns called start and end for your ranges, you could use a clause like this

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

    i.e. check the start of your test range is before the end of the database range, and that the end of your test range is after or on the start of the database range.

    0 讨论(0)
  • 2020-11-22 16:20
    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;
    
    0 讨论(0)
提交回复
热议问题