MySQL Запрос не работает во всех тестовых случаях - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть следующая структура таблицы с дневными сменами.

Только в смену C время делится на два дня.

Как видите C Смена начинается в 20: 30 и заканчивается в следующие дни 06: 00 .

Структура таблицы и данные следующим образом

create table `machine_shifts` (
   `date` date ,
   `shift_start_time` time ,
   `shift_end_time` time ,
   `shift` varchar (60),
   `updated_on` timestamp 
);

insert into `machine_shifts` (`date`, `shift_start_time`, `shift_end_time`, `shift`, `updated_on`) values('2010-01-01','06:00:00','14:30:00','A','2020-01-29 15:37:26'),
('2010-01-01','14:30:00','22:30:00','B','2020-01-29 15:37:26'),
('2010-01-01','22:30:00','06:00:00','C','2020-01-29 15:37:26'),
('2010-01-02','06:00:00','14:30:00','A','2020-01-29 15:37:26'),
('2010-01-02','14:30:00','22:30:00','B','2020-01-29 15:37:26'),
('2010-01-02','22:30:00','06:00:00','C','2020-01-29 15:37:26'),
('2010-01-03','06:00:00','14:30:00','A','2020-01-29 15:37:26'),
('2010-01-03','14:30:00','22:30:00','B','2020-01-29 15:37:26'),
('2010-01-03','22:30:00','06:00:00','C','2020-01-29 15:37:26'),
('2010-01-04','06:00:00','14:30:00','A','2020-01-29 15:37:26'),
('2010-01-04','14:30:00','22:30:00','B','2020-01-29 15:37:26'),
('2010-01-04','22:30:00','06:00:00','C','2020-01-29 15:37:27');

Данные представлены следующим образом

enter image description here

Теперь с помощью следующего запроса Я получаю данные между двумя диапазонами дат. то есть между '2010-01-02 00: 00: 00' и '2010-01-03 10: 00: 00' .

SELECT * FROM machine_shifts
WHERE 
CONCAT(`date`, ' ', shift_start_time)
    BETWEEN '2010-01-02 00:00:00' AND '2010-01-03 10:00:00'
OR 
CONCAT(`date`, ' ', shift_end_time) + INTERVAL (shift = 'C') DAY
    BETWEEN '2010-01-02 00:00:00' AND '2010-01-03 10:00:00'
ORDER BY `date`, shift_start_time ASC

С помощью вышеприведенного запроса я получаю enter image description here

И это набор результатов, которого я очень ожидал. Я мог этого добиться отправив еще один вопрос ранее.

Приведенный выше запрос работает, но он работает только тогда, когда две даты различны, но когда я хочу получить данные между двумя разными периодами времени в пределах одной и той же даты, я Я не получаю ожидаемых данных. Пожалуйста, найдите следующий пример диапазонов дат и времени.
-> '2010-01-01 07:01:00' И '2010-01-01 14: 00: 00' С этим я должен следующие ожидаемые данные, но я получаю пустой набор результатов.

enter image description here

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

Редактировать: Просто обнаружил, что даже в приведенном выше запросе есть проблема с этим диапазоном '2010-01-02 00:00:00' И '2010-01-03 14: 30: 00'

SELECT * FROM machine_shifts
WHERE 
CONCAT(`date`, ' ', shift_start_time)
BETWEEN '2010-01-02 00:00:00' AND '2010-01-03 14:30:00'
OR 
CONCAT(`date`, ' ', shift_end_time) + INTERVAL (shift = 'C') DAY
BETWEEN '2010-01-02 00:00:00' AND '2010-01-03 14:30:00'
ORDER BY `date`, shift_start_time ASC

Здесь я получаю enter image description here

Здесь я совсем не ожидаю последнего ряда.

Как могу ли я достичь этого? Можете ли вы предложить мне лучший подход ## Заголовок ##

Ответы [ 3 ]

2 голосов
/ 10 февраля 2020
SELECT * FROM machine_shifts
WHERE CONCAT(`date`, ' ', shift_start_time) <= @end
AND
CONCAT(`date`, ' ', shift_end_time) + INTERVAL (shift = 'C') DAY >= @start
ORDER BY `date`, shift_start_time ASC;

fiddle

Два временных диапазона перекрываются, когда оба (начало одного диапазона меньше конца другого диапазона). Или «не более чем» для «перекрывающегося или смежного» варианта, как в моем решении / скрипке.

1 голос
/ 10 февраля 2020

Каждая смена машины происходит с одной временной отметки на другую. Однако в вашей модели данных вы сохраняете только метку времени начала, разделенную на дату и время без видимой причины, и время окончания. Этого недостаточно, поскольку СУБД не может знать, в какую дату должно быть указано время окончания. Это только в вашей голове. Вместо этого у вас должна быть либо конечная дата-время, либо длительность смены.

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

with shifts as
(
  select
    addtime(`date`, shift_start_time) as start_time,
    addtime(`date` + interval case when shift_end_time < shift_start_time then 1 else 0 end day,
           shift_end_time) as end_time,
    shift,
    updated on
  from machine_shifts
)
select *
from shifts
where start_time <= timestamp '2010-01-01 07:01:00' 
  and end_time >= timestamp '2010-01-01 14:00:00';

(Примечание: будьте осторожны при добавлении времени к дате. MySQL не сделайте это правильно и получите неправильный результат. Вот почему я показываю ADDTIME вместо простого + выше.)

0 голосов
/ 10 февраля 2020

Вы можете использовать

TIMEDIFF

select TIMEDIFF(cast(CONCAT('2010-01-01 ','06:00:00') as datetime),
cast(CONCAT('2010-01-01 ','14:30:00') as datetime));
...