Q:

Как написать запрос, чтоб учесть все 4 даты?

Мне нужно найти наиболее подходящую дату между датами "план" и датами "факт". 
Дата имеет начало и конец работы. Запланированная дата начала работы может быть меньше факта и наоборот, фактическая дата может быть меньше запланированной.
BD имеет 5 колонок: id, dateFactStart, datePlanStart, dateFactEnd, dateFactStart.

A:

Схема БД
Будем использовать такую схему
CREATE TABLE `plan_fact`(
  id INT UNSIGNED AUTO_INCREMENT,
  datePlanStart DATE,
  datePlanEnd DATE,
  dateFactStart DATE,
  dateFactEnd DATE,
  description VARCHAR(64) NOT NULL,
  PRIMARY KEY(id)
);

Тестовые данные
Наполним таблицу план-факта данными:
INSERT INTO `plan_fact` VALUES
(DEFAULT, '2019-01-01', '2019-01-08', '2018-12-31', '2019-01-02', 'пересечение  (кейс 1)'),
(DEFAULT, '2019-01-01', '2019-01-08', '2019-01-02', '2019-01-10', 'пересечение  (кейс 2)'),
(DEFAULT, '2019-01-01', '2019-01-08', '2019-01-01', '2019-01-08', 'полное совпадение'),
(DEFAULT, '2019-01-01', '2019-01-08', '2018-12-31', '2019-01-01', 'пересекаются в 1 дне (кейс 1)'),
(DEFAULT, '2019-01-01', '2019-01-08', '2019-01-08', '2019-01-20', 'пересекаются в 1 дне (кейс 2)'),
(DEFAULT, '2019-01-01', '2019-01-08', '2018-12-30', '2018-12-31', 'не пересекаются (кейс 1)'),
(DEFAULT, '2019-01-01', '2019-01-08', '2019-01-09', '2019-01-20', 'не пересекаются (кейс 2)'),
(DEFAULT, '2019-01-01', '2019-01-30', '2019-01-02', '2019-01-03', 'включение "факта" в "план"'),
(DEFAULT, '2019-01-02', '2019-01-03', '2019-01-01', '2019-01-30', 'включение "плана" в "факт"'),
(DEFAULT, '2019-01-01', NULL, '2018-12-31', '2019-01-02', 'пересечение в дате начала плана + NULL (кейс 1)'),
(DEFAULT, '2019-01-01', NULL, '2019-01-02', '2019-01-10', 'NULL (кейс 2)'),
(DEFAULT, '2019-01-01', '2019-01-30', '2019-01-02', NULL, 'NULL (кейс 3)'),
(DEFAULT, '2019-01-01', '2019-01-30', NULL, NULL, 'NULL (кейс 4)'),
(DEFAULT, '2019-01-01', '2019-01-30', NULL, NULL, 'NULL (кейс 5)')
;

Поиск общей даты
Если представить время как линию, а "план" и "факт" в виде отрезков с началом и концом, то возможны 4 варианта:

пересечение (дата начала или конца одного отрезка находится внутри другого отрезка времени)
полное совпадение
включение (дата начала и конца одного отрезка времени полностью поглощены другим отрезком времени)
не имеют общей даты

Запрос, показывающий это (1 - сработало условие, 0 - нет):
SELECT
  (datePlanStart BETWEEN dateFactStart AND dateFactEnd) AS `intersect_1`,
  (datePlanEnd BETWEEN dateFactStart AND dateFactEnd) AS `intersect_2`,
  (datePlanStart <= dateFactStart AND datePlanEnd >= dateFactEnd) AS `include`,
  description
FROM plan_fact;

Результат:
+-------------+-------------+---------+--------------------------------------------------------------------------------+
| intersect_1 | intersect_2 | include | description                                                                    |
+-------------+-------------+---------+--------------------------------------------------------------------------------+
|           1 |           0 |       0 | пересечение  (кейс 1)                                                          |
|           0 |           1 |       0 | пересечение  (кейс 2)                                                          |
|           1 |           1 |       1 | полное совпадение                                                              |
|           1 |           0 |       0 | пересекаются в 1 дне (кейс 1)                                                  |
|           0 |           1 |       0 | пересекаются в 1 дне (кейс 2)                                                  |
|           0 |           0 |       0 | не пересекаются (кейс 1)                                                       |
|           0 |           0 |       0 | не пересекаются (кейс 2)                                                       |
|           0 |           0 |       1 | включение "факта" в "план"                                                     |
|           1 |           1 |       0 | включение "плана" в "факт"                                                     |
|           1 |        NULL |       0 | пересечение в дате начала плана + NULL (кейс 1)                                |
|           0 |        NULL |    NULL | NULL (кейс 2)                                                                  |
|           0 |        NULL |    NULL | NULL (кейс 3)                                                                  |
|        NULL |        NULL |    NULL | NULL (кейс 4)                                                                  |
|        NULL |        NULL |    NULL | NULL (кейс 5)                                                                  |
+-------------+-------------+---------+--------------------------------------------------------------------------------+

Теперь будем вместо булева значения выбирать дату:
SELECT
  IF(datePlanStart BETWEEN dateFactStart AND dateFactEnd, datePlanStart, NULL)
    AS `intersect_1`,
  IF(datePlanEnd BETWEEN dateFactStart AND dateFactEnd, datePlanEnd, NULL)
    AS `intersect_2`,
  IF(datePlanStart <= dateFactStart AND datePlanEnd >= dateFactEnd, datePlanStart, NULL)
    AS `include`,
  description
FROM plan_fact;

Результат:
+-------------+-------------+------------+--------------------------------------------------------------------------------+
| intersect_1 | intersect_2 | include    | description                                                                    |
+-------------+-------------+------------+--------------------------------------------------------------------------------+
| 2019-01-01  | NULL        | NULL       | пересечение  (кейс 1)                                                          |
| NULL        | 2019-01-08  | NULL       | пересечение  (кейс 2)                                                          |
| 2019-01-01  | 2019-01-08  | 2019-01-01 | полное совпадение                                                              |
| 2019-01-01  | NULL        | NULL       | пересекаются в 1 дне (кейс 1)                                                  |
| NULL        | 2019-01-08  | NULL       | пересекаются в 1 дне (кейс 2)                                                  |
| NULL        | NULL        | NULL       | не пересекаются (кейс 1)                                                       |
| NULL        | NULL        | NULL       | не пересекаются (кейс 2)                                                       |
| NULL        | NULL        | 2019-01-01 | включение "факта" в "план"                                                     |
| 2019-01-02  | 2019-01-03  | NULL       | включение "плана" в "факт"                                                     |
| 2019-01-01  | NULL        | NULL       | пересечение в дате начала плана + NULL (кейс 1)                                |
| NULL        | NULL        | NULL       | NULL (кейс 2)                                                                  |
| NULL        | NULL        | NULL       | NULL (кейс 3)                                                                  |
| NULL        | NULL        | NULL       | NULL (кейс 4)                                                                  |
| NULL        | NULL        | NULL       | NULL (кейс 5)                                                                  |
+-------------+-------------+------------+--------------------------------------------------------------------------------+

Теперь соединим все столбцы в один:
SELECT
IFNULL(
  IF(datePlanStart BETWEEN dateFactStart AND dateFactEnd, datePlanStart, NULL),
  IFNULL(
    IF(datePlanEnd BETWEEN dateFactStart AND dateFactEnd, datePlanEnd, NULL),
    IFNULL(
      IF(datePlanStart <= dateFactStart AND datePlanEnd >= dateFactEnd, datePlanStart, NULL),
      NULL
    )
  )
)
AS one_day,
description
FROM plan_fact;

Результат:
+------------+--------------------------------------------------------------------------------+
| one_day    | description                                                                    |
+------------+--------------------------------------------------------------------------------+
| 2019-01-01 | пересечение  (кейс 1)                                                          |
| 2019-01-08 | пересечение  (кейс 2)                                                          |
| 2019-01-01 | полное совпадение                                                              |
| 2019-01-01 | пересекаются в 1 дне (кейс 1)                                                  |
| 2019-01-08 | пересекаются в 1 дне (кейс 2)                                                  |
| NULL       | не пересекаются (кейс 1)                                                       |
| NULL       | не пересекаются (кейс 2)                                                       |
| 2019-01-01 | включение "факта" в "план"                                                     |
| 2019-01-02 | включение "плана" в "факт"                                                     |
| 2019-01-01 | пересечение в дате начала плана + NULL (кейс 1)                                |
| NULL       | NULL (кейс 2)                                                                  |
| NULL       | NULL (кейс 3)                                                                  |
| NULL       | NULL (кейс 4)                                                                  |
| NULL       | NULL (кейс 5)                                                                  |
+------------+--------------------------------------------------------------------------------+

