Summing range of dates without counting overlaps in mysql

前端 未结 3 1941
遇见更好的自我
遇见更好的自我 2021-01-26 18:09

I have simple table with start_date and end_date columns in it. These date values may overlap

id    start_date    end_date
1     2011-0         


        
相关标签:
3条回答
  • 2021-01-26 18:12

    If you need the total periods for a number of records including the overlaps, then simply sum the period differences per record:

    SELECT SUM(PERIOD_DIFF( DATE_FORMAT(end_date, '%Y%m') , DATE_FORMAT(start_date, '%Y%m') )) AS total_periods
    FROM table WHERE ...
    
    0 讨论(0)
  • 2021-01-26 18:23

    This is hectic as anything but should get you what you need:

    SELECT SUM(PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM a.end_date), EXTRACT(YEAR_MONTH FROM a.start_date))) months
      FROM (
        SELECT MIN(g.start_date) start_date, MAX(g.end_date) end_date 
          FROM (
            SELECT @group_id := @group_id + (@end_date IS NULL OR o.start_date > @end_date) group_id,
                   start_date,
                   @end_date := DATE(CASE 
                     WHEN (@end_date IS NULL OR o.start_date > @end_date) THEN o.end_date
                     ELSE GREATEST(o.end_date, @end_date)
                   END) end_date  
              FROM overlap o
              JOIN (SELECT @group_id := 0, @end_date := NULL) init
          ORDER BY o.start_date ASC  
                ) g
      GROUP BY  g.group_id  
            ) a
    

    The inner-most query groups together your periods in overlapping groups stretching the end_date where appropriate. The end_date flexes as I assumed that there could be periods completely enclosed by the previous.

    The next wrapping query extracts the full range from each group.

    The outer query sums up the full month diffs for each group. All group diffs are rounded down to the nearest full month by PERIOD_DIFF.

    Unfortunately I couldn't test this as SQLFiddle has died on me.

    0 讨论(0)
  • 2021-01-26 18:23

    I did it my own way checking other answers here on Stackoverflow, it should work:

    select sum(months)
    from (select t.*, 
             @time := if(@sum = 0, 0, period_diff(date_format(start_date, '%Y%m'), date_format(@prevtime, '%Y%m'))) as months,
             @prevtime := start_date,
             @sum := @sum + isstart
      from ((select start_date, 1 as isstart
             from position t
            ) union all
            (select end_date, -1
             from position t
            )
           ) t cross join
           (select @sum := 0, @time := 0, @prevtime := 0) vars 
      order by 1, 2
     ) t
    
    0 讨论(0)
提交回复
热议问题