Как получить расписание персонала на определенную неделю

#mysql #laravel

Вопрос:

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

Вот моя схема базы данных и некоторые данные, а также SQLFiddle того же:

 -- schema
CREATE TABLE schedules (
    id INT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    day_of_week INT NOT NULL,
    start_date VARCHAR(25) NOT NULL,
    end_date VARCHAR(25),
    PRIMARY KEY(id)
);

-- data
INSERT INTO schedules
    (id, user_id, day_of_week,start_date,end_date)
VALUES
    (1, 2,1,"2021-05-03","2021-05-24"),
    (2, 2,1,"2021-05-31","2021-05-31"),
    (3, 2,1,"2021-06-07",null),
    (4, 2,2,"2021-05-04",null),
    (5, 2,3,"2021-05-05",null),
    (6, 2,4,"2021-05-06",null),
    (7, 2,5,"2021-05-07",null),
    (8, 2,6,"2021-05-08",null),
    (9, 3,1,"2021-04-12","2021-05-31"),
    (10, 3,1,"2021-06-07",null),
    (11, 3,2,"2021-05-11","2021-06-08"),
    (12, 3,2,"2021-06-15",null),
    (13, 3,3,"2021-05-05",null),
    (14, 3,4,"2021-05-06",null),
    (15, 3,5,"2021-05-07",null),
    (16, 3,6,"2021-05-08",null);
 

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

Ожидаемый результат должен быть таким, как показано ниже, для разных недель

 2021-05-09 to 2021-05-21

 ---- --------- ------------- ------------ ------------ 
| id | user_id | day_of_week | start_date | end_date   |
 ---- --------- ------------- ------------ ------------ 
|  1 |       2 |           1 | 2021-05-03 | 2021-05-24 |
 ---- --------- ------------- ------------ ------------ 
|  9 |       3 |           1 | 2021-04-12 | 2021-05-31 |
 ---- --------- ------------- ------------ ------------ 

2021-05-30 to 2021-06-05

 ---- --------- ------------- ------------ ------------ 
| id | user_id | day_of_week | start_date | end_date   |
 ---- --------- ------------- ------------ ------------ 
|  2 |       2 |           1 | 2021-05-31 | 2021-05-31 |
 ---- --------- ------------- ------------ ------------ 
| 10 |       3 |           1 | 2021-06-07 | NULL       |
 ---- --------- ------------- ------------ ------------ 

2021-06-13 to 2021-06-19

 ---- --------- ------------- ------------ ------------ 
| id | user_id | day_of_week | start_date | end_date   |
 ---- --------- ------------- ------------ ------------ 
|  3 |       2 |           1 | 2021-06-07 | NULL       |
 ---- --------- ------------- ------------ ------------ 
| 10 |       3 |           1 | 2021-06-07 | NULL       |
 ---- --------- ------------- ------------ ------------ 
 

в настоящее время я выполняю следующий запрос в инкрементном цикле от 2021-06-13 до 2021-06-19 в Laravel

 select
  *
from
`schedules`
where
  and `start_date` <= '2021-05-13' // 2021-05-14,2021-05-15 etc.
  and `day_of_week` = 0 // 1,2,3 etc.
  and (
    `end_date` >= '2021-05-18'
    or `end_date` is null )
 

Ниже приведен мой код Laravel для того же

     $start_date = new Carbon($data['start_date']);
    $start_date->startOfWeek(Carbon::SUNDAY);

    $schedule = [];

    for ($i = 0; $i <= 6; $i  ) {

        $schedule[] = StaffSchedule::
            where('start_date', '<=', $start_date->format('Y-m-d'))
            ->where('day_of_week',$start_date->dayOfWeek)
            ->where(function ($query) use ($start_date) {
                $query->where('end_date','>=',$start_date->format('Y-m-d'));
                $query->orWhereNull('end_date');
            })->orderBy('user_id')->get();

        $start_date = $start_date->addDay();
    }
 

Приведенный выше код запускает 7 запросов, по 1 на каждый день недели.

Можно ли объединить и выполнить один запрос?

Спасибо

Комментарии:

1. Попытка отобразить еженедельное расписание персонала на данную неделю. Например, текущая неделя, начинающаяся с 2021-06-06 to 2021-06-12` для запроса пользователя 2 должна возвращать строку 3. для недели, начинающейся с 2021-05-16 2021-05-21 запроса to, должна возвращать строку 1.

2. @Strawberry обновил вопрос, набор данных из SQLFiddle правильный.

3. @Strawberry в основном я хотел бы знать, какие пользователи работают или нет, передавая дату начала и дату окончания недели.

4. @Strawberry в таблице есть и другие поля schedules , такие как location_id , shift_start_time и shift_end_time и break_at т. Д.

Ответ №1:

В качестве отправной точки рассмотрим следующее:

 SELECT * 
  FROM schedules 
 WHERE start_date <= '2021-05-15' 
   AND COALESCE(end_date,start_date) >= '2021-05-09';
 ---- --------- ------------- ------------ ------------ 
| id | user_id | day_of_week | start_date | end_date   |
 ---- --------- ------------- ------------ ------------ 
|  1 |       2 |           1 | 2021-05-03 | 2021-05-24 |
 ---- --------- ------------- ------------ ------------ 

SELECT * 
  FROM schedules 
 WHERE start_date <= '2021-06-05' 
   AND COALESCE(end_date,start_date) >= '2021-05-31';
 ---- --------- ------------- ------------ ------------ 
| id | user_id | day_of_week | start_date | end_date   |
 ---- --------- ------------- ------------ ------------ 
|  2 |       2 |           1 | 2021-05-31 | 2021-05-31 |
 ---- --------- ------------- ------------ ------------ 

SELECT * 
  FROM schedules 
 WHERE start_date <= '2021-06-06'   INTERVAL 1 WEEK 
   AND COALESCE(end_date,start_date) >= '2021-06-06';
 ---- --------- ------------- ------------ ---------- 
| id | user_id | day_of_week | start_date | end_date |
 ---- --------- ------------- ------------ ---------- 
|  3 |       2 |           1 | 2021-06-07 | NULL     |
 ---- --------- ------------- ------------ ---------- 
 

Комментарии:

1. Это происходит с небольшой настройкой

2. не запрашивая результат, я не уверен, является ли end_date поле пустым или нет, так как бы я узнал, какой запрос использовать??

3. Все они одинаковы в отношении end_date, но я отредактирую последнее в качестве подсказки…

4. Я обновил вопрос и также включил ожидаемый результат.