Content Notice!

This post is really old, and no longer reflect my skill level, views or opinions, it is made available here for archival purposes (it was originally on my old WordPress blog).

Keep that in mind when you read the contents within.

Intersecting/overlapping dates in MySQL

I recently tried to solve a problem of checking if a certain user was available for work within a certain time period based on other entries in a table containing start and end dates.

When searching online I didn't find quite as much information as I had hoped, however found a very useful illustration that helped me visualize the problem more easily

From this i wrote the following SQL code

SELECT
    start_date,
   end_date
FROM table
WHERE (
     (`start_date` <= '2017-05-01' AND `end_date` >= '2017-04-01')
  OR (`start_date` >= '2017-05-01' AND `start_date` <= '2017-04-01' AND `end_date` <= '2017-04-01')
  OR (`end_date` <= '2017-04-01' AND `end_date` >= '2017-05-01' AND `start_date` <= '2017-05-01')
  OR (start_date >= '2017-05-01' AND start_date <= '2017-04-01')
)

Another interesting problem I had is that in my case, the table did not contain the end_date column, however contained a duration column, which measured the duration of a certain job in days, from this we can use some MySQL Function magic to create a column alias that will be the end_date:

When doing this we have to use HAVING instead of WHERE because WHERE can not perform "queries" on column aliases.

SELECT
    start_date,
   DATE_ADD(start_date, INTERVAL duration DAY) AS end_date
FROM jobs
HAVING (
      (`start_date` <= '2017-05-01' AND `end_date` >= '2017-04-01')
   OR (`start_date` >= '2017-05-01' AND `start_date` <= '2017-04-01' AND `end_date` <= '2017-04-01')
   OR (`end_date` <= '2017-04-01' AND `end_date` >= '2017-05-01' AND `start_date` <= '2017-05-01')
   OR (start_date >= '2017-05-01' AND start_date <= '2017-04-01')
);

If you get the following error:

Non-grouping field 'start_date' is used in HAVING clause

Try disabling strict mode, if you are using laravel, you have to edit your mysql driver in config/database.php like this:

'mysql' => [
    'driver' => 'mysql',
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
    'modes' => [  // <- Add this
        'STRICT_TRANS_TABLES',
        'NO_ZERO_IN_DATE',
        'NO_ZERO_DATE',
        'ERROR_FOR_DIVISION_BY_ZERO',
        'NO_AUTO_CREATE_USER',
        'NO_ENGINE_SUBSTITUTION'
    ]
],

I hope that helps the next poor soul that have a similar problem.