Отображать события планировщика каждую неделю от даты начала до даты окончания - PullRequest
0 голосов
/ 12 декабря 2018

Последние два дня я чесал голову - мне нужен экспертный взгляд!

По сути, я пытаюсь отображать события планировщика для водителей в течение 1 недели, пока они не выключены.Если водитель отключен с 10 декабря 2018 года по 21 декабря 2018 года, я хочу, чтобы водитель перенес его на следующий день, и его / ее имя отображалось до даты окончания.Прямо сейчас результат отображает только драйвер для текущего дня, а не повторяется каждый день.

Вот пример набора данных:

CREATE TABLE IF NOT EXISTS planner_events (
  planner_id INT(5) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  event_name VARCHAR(100) NOT NULL,     
  event_start_date DATE,    
  event_end_date DATE,
  user_id INT(5) NOT NULL,  
  user_type VARCHAR(10) NOT NULL,
  date_created DATETIME DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO planner_events (event_name, event_start_date, event_end_date, user_id, user_type)
VALUES ('Annual Holiday', '2018-12-12', '2018-12-16', 101, 'driver'), 
('Alex on leave', '2018-12-12', '2018-12-15', 102, 'driver'), 
('Reminder', '2018-12-13', '2018-12-13', 103, 'driver');

CREATE TABLE IF NOT EXISTS drivers (
  driver_id INT(5) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  driver_name VARCHAR(100) NOT NULL, 
  date_created DATETIME DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO drivers (driver_id, driver_name)
VALUES (101, 'Alex'), (102, 'Tom'),(103, 'Trevor');

Я создал скрипту SQL, ноВ скрипте SQL по умолчанию не хранится таблица seq_0_to_999999.Я использую последнюю версию MariaDB.

SQL Fiddle Link

Вы можете скопировать таблицы и операторы SQL из приведенного выше на локальном компьютере, если у вас естьУстановлена ​​MariaDB.

По сути, в коде с помощью функции in_array я буду удалять драйверы из поля доступности, если они выключены в определенный день.Я пытаюсь добиться этого с помощью 1 запроса, где он получает пустые дни недели или где отключены драйверы.В настоящее время запрос работает только в том случае, если есть запись для данного дня, и проблема в том, что он не переносится, если дата окончания еще не закончена.

enter image description here

Вот хороший пример выполнения текущего запроса.Если вы посмотрите на экран, показанный ниже, Марио не будет работать до 01.01.2009, но дни 19, 20, 21, 22 и 23 не заполнены и не говорят его имя.Возможно, им нужен КРЕСТ-РЕЙТИНГ где-то - думая логически!

enter image description here

Любая помощь будет принята с благодарностью и спасибо, что нашли время!

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Я нашел запрос в вашей скрипке немного сложным для подражания.Но я думаю, что вы хотите вот что:

select *
from planner_events e
join drivers d on d.driver_id=e.user_id
where e.event_start <= @enddate and e.event_end >= @startdate
  and e.user_type='driver'

Где @startdate - первый день интересующего вас периода, а @enddate - последняя дата.Если размер диапазона всегда один и тот же, одна неделя или что-то еще, @enddate можно заменить вычислением.

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

О, и, конечно же, вместо "select *" вы должны перечислить все поля, которые вы используете.на самом деле заинтересован. Я просто ленился там.

Обновление

А, понятно.Вам нужен список тех, кто доступен каждый день, а не только тех, кто доступен где-то в течение недели.

Хорошо, насколько мне известно, для этого вам понадобится таблица с записями для каждого дня.,Существует множество способов создания такой таблицы, я не знаю, как использовать стандартный SQL.Если создание этой таблицы является проблемой, которую мы можем решить, но позвольте мне предположить, что это не так, и что такая таблица существует и называется «рабочими днями», и каждая запись включает поле даты «date1».

Затемзапрос может быть выполнен следующим образом:

select w.date1, d.driver_id, d.driver_name
from workdays w
cross join drivers d
where w.date1 between @start and @end
 and not exists (select * from planner_event 
   where event_start<=w.date1 and event_end>=w.date1 and user_id=d.driver_id and user_type='driver')
order by w.date1, d.driver_id

Это дает набор результатов со списком дат и доступных драйверов, которые затем необходимо будет отформатировать в нужной таблице с кодом.Если вы ищете в наборе результатов по одному столбцу для каждого дня и по одной строке для каждого драйвера или чего-то подобного, я уверен, что мы могли бы это сделать, придется поиграть с этим немного больше.Я думаю, что это был бы беспорядочный запрос с подзапросом на каждый день.

Обновление 2

Ах.Если мы знаем, что период - неделя, то нам не нужен рабочий день.Мы можем сделать это:

select d.driver_id, d.driver_name,
  case when exists (select * from planner_events where '2018-12-31' between event_start_date and event_end_date and user_id=d.driver_id) then 'N' else 'Y' end as Monday,
  case when exists (select * from planner_events where DATE_ADD('2018-12-31', INTERVAL 1 DAY) between event_start_date and event_end_date and user_id=d.driver_id) then 'N' else 'Y' end as Tuesday,
  case when exists (select * from planner_events where DATE_ADD('2018-12-31', INTERVAL 2 DAY) between event_start_date and event_end_date and user_id=d.driver_id) then 'N' else 'Y' end as Wednesday,
  case when exists (select * from planner_events where DATE_ADD('2018-12-31', INTERVAL 3 DAY) between event_start_date and event_end_date and user_id=d.driver_id) then 'N' else 'Y' end as Thursday,
  case when exists (select * from planner_events where DATE_ADD('2018-12-31', INTERVAL 4 DAY) between event_start_date and event_end_date and user_id=d.driver_id) then 'N' else 'Y' end as Friday
from drivers d
order by d.driver_id
0 голосов
/ 13 декабря 2018

Есть джентльмен по имени Андрей (https://dba.stackexchange.com/users/6965/andriy-m),, он помог мне в прошлом, и он ответил на это, как я и ожидал. Благодарю также @Jay за публикацию другого ответа на эту проблему.

Вот правильный SQL-запрос:

SELECT sub.planner_start_date, COALESCE(d.driver_name, 'N/A') AS driver_name, e.planner_id, e.event_name, e.event_start_date, e.event_start_time, e.event_end_date, e.event_end_time
FROM
( SELECT
        '2018-12-30' + INTERVAL seq.seq DAY AS planner_start_date
     FROM
        seq_0_to_999999 AS seq
     WHERE
        seq.seq <= TIMESTAMPDIFF(DAY, '2018-12-30', '2019-01-05')
    ) as sub
LEFT JOIN planner_events AS e ON e.event_start_date <= sub.planner_start_date AND e.event_end_date >= sub.planner_start_date
LEFT JOIN drivers AS d ON e.user_id = d.driver_id AND e.user_type = 'driver'

Спасибо всем за помощь в этом.

0 голосов
/ 12 декабря 2018

Мне кажется, что это все, что вам нужно:

SELECT d.driver_id
     , d.driver_name
     , e.planner_id
     , e.event_name
     , e.event_start_date
     , e.event_end_date
  FROM drivers d 
  JOIN planner_events e 
    ON e.user_id = d.driver_id;

Все остальное может показаться проблемой отображения - лучше всего разрешается в коде приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...