2016-11-25 4 views
0

мне нужна помощь запрашивая мой календарь/таблица датыSQL/Mysql запросов доступные даты и времени в базе данных

Сценарий: У меня есть «календарь» таблица с датами и временем (см ниже), пользователи смогут установить их наличии даты, обычно день за днем ​​с доступными временными интервалами на каждый день. Так что моя таблица выглядит следующим образом:

+------+------------+---------------------+---------------------+ 
| ID | user_id | start_date   | end_date   | 
+------+------------+---------------------+---------------------+ 
| 1 |   1 | 2016-09-01 08:00:00 | 2016-09-01 16:00:00 | 
| 2 |   1 | 2016-09-03 00:00:00 | 2016-09-03 23:59:59 | 
| 3 |   1 | 2016-09-04 00:00:00 | 2016-09-04 16:00:00 | 
| 4 |   1 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 | 
| 5 |   2 | 2016-09-05 08:00:00 | 2016-09-05 16:00:00 | 
| 6 |   2 | 2016-09-07 08:00:00 | 2016-09-07 16:00:00 | 
| 7 |   2 | 2016-09-08 08:00:00 | 2016-09-08 16:00:00 | 
| 8 |   2 | 2016-09-08 18:00:00 | 2016-09-08 22:00:00 | 
+------+------------+---------------------+---------------------+ 

У нас есть 2 пользователей здесь, поэтому я хочу следующее:

  • Если я ищу датой_начала = 2016-09-05 8:00:00 и end_date = 2016-09-05 16:00:00 он должен возвращать пользователя 1 и 2. Поскольку у обоих из них есть запись с этими датами. То же самое происходит, если start_date = 2016-09-05 09:00:00 и end_date = 2016-09-05 15:00:00, это должно также вернуть обоих пользователей с момента поиска im, между временными интервалами, как показанном в примере.

  • Второй сценарий немного сложнее, если пользователь ищет start_date = 2016-09-03 08:00:00 и end_date = 2016-09-04 16:00:00 Я хочу, чтобы запрос проверял следующие:

    • Посмотрите, доступен ли пользователь каждый день в это время.
    • поэтому в этом случае пользователь доступен в 2016-09-03 между 08:00:00 и 16:00:00, а также с 2016-09-04 между 08:00:00 и 16:00: 00.
    • В примере по этому поводу должен возвращать пользователь 1.

Im открыт для предложения на вновь разработанные мою схему, если это необходимо.

Надеюсь, что некоторые из них могут мне помочь.

ответ

0

DEMO содержит некоторые комментарии к внешнему коду и показывает, как изменяется запрос. Также я добавляю еще одну строку для user_id = 2, чтобы показать, как соответствовать только одному из двух дней в диапазоне.

SELECT U.`user_id` 
FROM (
     select a.selectDate, 
       CONCAT(a.selectDate, ' ', time(@s_date)) as start_time, 
       CONCAT(a.selectDate, ' ', time(@s_date)) as end_time 
     from (
      select '1900-01-01' + INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY as selectDate 
      from  (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a 
      cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b 
      cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c 
      cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d 
      cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as e 
     ) a 
     CROSS JOIN (SELECT @s_date := '2016-09-03 08:00:00', @e_date := '2016-09-04 16:00:00') par 
     -- CROSS JOIN (SELECT @s_date := '2016-09-05 08:00:00', @e_date := '2016-09-05 16:00:00') par 
     -- CROSS JOIN (SELECT @s_date := '2016-09-05 09:00:00', @e_date := '2016-09-05 15:00:00') par 
     WHERE selectDate BETWEEN date(@s_date) 
          AND date(@e_date) 
    ) D 
CROSS JOIN (SELECT DISTINCT `user_id` FROM Table1) U 
LEFT JOIN Table1 T 
     ON U.`user_id` = T.`user_id` 
     AND D.start_time <= T.`end_date` 
     AND D.end_time >= T.`start_date` 
GROUP BY U.`user_id` 
HAVING COUNT(U.`user_id`) = COUNT(T.`user_id`); 

ВЫВОД

  • Шаг 1: создать список дат, в данном случае 273 лет
  • Шаг 2: выбрать все даты между диапазоном определения в параметрах, а также включают в себя время на каждую дату.
  • Шаг 3: соединить все вместе, чтобы увидеть, что сроки у пользователя в этом временном окне
  • Шаг 4: выберите только пользователю окно времени для всех дат

enter image description here

+0

Первый случай его работы но не второй. Если я ищу от 2016-09-01 08:00:00 до 2016-09-04 17:00:00 Я получаю 3 результата с пользователем 1, но должен получить только 1. Пользователь 1 доступен только на 2016- 09-03 с 08:00:00 до 17:00:00. –

+0

Я отвечаю только на первую часть, вторая требует много работы, не очень тривиальна.Вам нужно разбить диапазон на несколько дат –

+0

проверить версию обновления. –

Смежные вопросы