-2

On my database table I have 2 columns, start_date and end_date.

Sample data would be:

-------------------------------
start_date     |     end_date
-------------------------------
2017-11-01           2017-11-02
2017-11-03           2017-11-07
2017-11-20           2017-11-28
2017-11-13           2017-12-02
-------------------------------

I need to find if there are 5 consecutive days that are not yet used, which in this case, there is:

(2017-11-08 to 2017-11-13)

I'm using PHP and MySQL.

Thanks in advance!

Strawberry
  • 33,750
  • 13
  • 40
  • 57
Lhen
  • 181
  • 3
  • 15

2 Answers2

3

You'd need to check for edge cases depending on your actual data and if there were no overlap dates, but this is a good start for the provided data.

Assuming table and data as defined as below:

CREATE TABLE
  `appointments`
 (
     `appointment_id` INT PRIMARY KEY AUTO_INCREMENT,
     `start_date` DATE,
     `end_date` DATE
 );

INSERT INTO
     `appointments`
 (`start_date`, `end_date`)
 VALUES
 ('2017-11-01', '2017-11-02'),
 ('2017-11-03', '2017-11-07'),
 ('2017-11-20', '2017-11-28'),
 ('2017-11-13', '2017-12-02');

If you order the rows, and take the lag from the end date before it, and take any gaps of 5 or more. In SQL Server there are LAG functions, but here's a way of doing the same. Then once you have a table of all rows and their corresponding gaps, you take the start date of that period, and create the gap period from the number of days between. Since TIMESTAMPDIFF is inclusive, you need to subtract a day.

SET @end_date   = NULL;

SELECT 
   DATE_ADD(`start_date`, INTERVAL -(`gap_from_last`-1) DAY) AS `start_date`,
   `start_date` AS `end_date`
FROM
(
SELECT
    `appointment_id`,
    CASE 
      WHEN @end_date IS NULL THEN NULL
      ELSE TIMESTAMPDIFF(DAY, @end_date, `start_date`) 
    END AS `gap_from_last`,
    `start_date`,
    @end_date   := `end_date` AS `end_date`  -- Save the lag date from the row before
FROM
    `appointments`
ORDER BY
    `start_date`,
    `end_date`
) AS `date_gap` -- Build table that has the dates and the number of days between
WHERE
  `gap_from_last` > 5;

Provides:

start_date | end_date
------------------------
2017-11-08 | 2017-11-13

Edit: Oops! Forgot the SQLFiddle (http://sqlfiddle.com/#!9/09cfce/16)

kchason
  • 2,836
  • 19
  • 25
0
SELECT x.end_date + INTERVAL 1 DAY unused_start
     , MIN(y.start_date) unused_end 
  FROM appointments x 
  JOIN appointments y 
    ON y.start_date >= x.end_date 
 GROUP 
    BY x.start_date  
HAVING DATEDIFF(MIN(y.start_date),unused_start) >= 5;
Strawberry
  • 33,750
  • 13
  • 40
  • 57