Виталий К.
55 сообщений
#14 лет назад
Подскажите, пожалуйста, как в БД оптимальнее хранить время работы заведений.

Например, такие:
Вт, Чт, Сб: 17.40-19.00
пн. - вс.: с 16:00 до 04:00
пт. - сб.: с 23:00 до 06:00
пн. - чт.: с 16:00 до 23:00

В дальнейшем, по этим данный, требуется искать заведения работающие в определенное время.

Например, требуется найти все заведения работающие во Вторник в 18.30.

Спасибо.
Роман Беляев
16382 сообщения
#14 лет назад
Каждая строка - запись времени работы ОТ и ДО. т.е. 2 поля типа time - начало промежутка и конец промежутка. id записи, id заведения. К каждому заведению можно привязать несколько таких записей. Соответственно на каждый день надо от одной записи. 2 если с перерывом.
Виталий К.
55 сообщений
#14 лет назад
Т.е. такая структура БД?

CREATE TABLE `vremya_raboty` (
`id` int(11) NOT NULL,
`id_zavedenie` int(11) NOT NULL,
`den_nedeli` tinyint(4) NOT NULL,
`ot_time` time NOT NULL,
`do_time` time NOT NULL,
PRIMARY KEY (`id`),
KEY `id_zavedenie` (`id_zavedenie`),
KEY `den_nedeli` (`den_nedeli`)
) ENGINE=MyISAM;



Получается такое время работы: ( Пн: от 18:00 до 6:00 )
еще нужно разбивать на две записи: ( Пн: от 18:00 до 24:00 ) and (Вт: от 00:00 до 6:00)
Роман Беляев
16382 сообщения
#14 лет назад
storier, вроде того, да. Вообще можно просто интами попробовать сделать. Тогда не придется разбивать при переходе через сутки. Начало будет 1800, конец - 600.
Денис Ш.
7132 сообщения
#14 лет назад
Цитата ("frig"):
Вообще можно просто интами попробовать сделать


Зачем?

Цитата ("frig"):
Тогда не придется разбивать при переходе через сутки. Начало будет 1800, конец - 600


Какая разница если хранить время в его собственном формате? А разбивать или нет по суткам зависит не от способа хранения, а от принципа учета.
Будет храниться: 5 1800 600 или 5 18:00 06:00 - какая разница от типа данных? Зачем извращаться с переводом из шестидесятиричной системы в десятичную и наоборот?

Вот, например, в табельном учете (что на заводах и шахтах) бывает такая переходящая смена (через полночь) учитывается только в сутках, когда началась, а бывает разбивается по суткам принадлежности. И при расчете ЗП такое рабочее время может по разному учитываться.

Так и тут, способ отображения переходящих через полночь будет целиком зависеть от поставленной задачи. Судя по головному сообщению, удобней все-таки разделять независимо от типа данных для времени - запрос все равно будет проще построить при разделенных строках.
Роман Беляев
16382 сообщения
#14 лет назад
Цитата ("shapod"):
Зачем?


Согласен, туплю. Это все ТС меня сбил :-))
Виталий К.
55 сообщений
#14 лет назад


Подскажите, структуру БД(mysql) для хранения времени работы из следующей формы для большого количества заведений.
Спасибо.
Роман П.
1599 сообщений
#14 лет назад
Если поиск потом не будет нужен (какое работает по понедельникам, какое по воскресеньям, какое с 10 до 11 в воскресенье) - то хранить данные только для вывода надо и поэтому храните их в любом виде, хоть в виде сериализованного php-массива.

Если поиск нужен и, особенно, если он будет достаточно расширенный, то лучше всего завести три таблицы - одну для дней недели, другую для временных интервалов и третью связующую, которая содержит айди заведения, айди дня недели и айди интервала.
Виталий К.
55 сообщений
#14 лет назад
Поиск нужен.

Но, наверное, не имеет смысла делать 3 таблицы. Id дня недели: 0-6, id временных интервалов от 0-23 сразу известны.
Роман П.
1599 сообщений
#14 лет назад
storier, наверное, не имеет, но тут надо хорошенько подумать все же, мне приходят на ум пара гипотетических ситуаций, когда легче будет вынимать данные из трех таблиц, чем из одной таблицы и с применением массивов дней недели и интервалов.. но они гипотетические, надо знать о чем проект и что планируется делать в будущем. Так что вам решать
Виталий К.
55 сообщений
#14 лет назад
Crist, каталог заведений.

Один из критериев поиска заведений, это временной: что работает в данный момент, что работает до хх часов, что работает с хх часов.

У некоторых время работы переходит через сутки.
Кирилл Е.
2817 сообщений
#14 лет назад
Ем.. на картинке что - декартовая система координат )..
Где х є ; y є ; x,y є N.. этим и можно воспользоваться, для 1 заведения будет один слой описывающий некую фигуру по некоторому уравнению, задача с уравнениями становится проще, так как заведомо известно, что фигура будет только с прямыми углами При выборе графика работы для 1 заведения получается функция, описывающая его работу на этой плоскости ..

и того:

таблица Заведения
Ид Название Уравнение графика работы

таблица Графики - эта таблица ненужна, данные статические и можно описать массивом в одном файле.

Поиск осуществляется таким образом: для поиска выбранные опции с этой декартовой плоскости, соответственно будет тоже уравнение.. остаётся выбрать такие заведения, которые "пересекаются" или "содержатся" в сгенерированном уравнении поиска, тоесть множество допустимых значений поиска и заведения совпадают минимум 1 квадратом.

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

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

..
Но можно пойти в "лоб" и делать таблицу типо:
Ид Название заведения Пн_8_9 Пн_9_10 .. Пт_18_19 Пт_19_20
Получится громоздкая таблица, но тоже вполне будет работать .. тут всем будет понятно, если для заведения в ячейке Чт_10_11 стоит "1" - то в четверг с 10 до 11 утра оно работает

УПД: на реализацию первого предложенного варианта уйдёт времени раза в 3-4 больше чем на второй, но первый прикольнее, будет выглядит впечатляюще, да и от процесса воплощения масса удовольствия
Константин П.
1351 сообщение
#14 лет назад
А чего бы не заносить информацию таким образом?

Рабочие Часы Заведения:

-> заведение
-> ->день
-> -> ->время начала работы с...
-> -> ->продолжительность работы
-> -> ->перерыв на обед с...
-> -> ->продолжительность обеда
Виталий К.
55 сообщений
#14 лет назад
kirilev, я больше получаю удовольствия от простых и оптимальных способов решения задач .

TomNorman, спасибо, тоже вариант. Нужно посмотреть насколько удобно будет искать по такой таблице.
Вадим Т.
3240 сообщений
#14 лет назад
Вот мой вариант решения.
Таблица:
— id — id заведения
— timefrom — время начала работы
— timeto — время окончания работы

Время является числом типа INT(5) UNSIGNED (в MySQL в данном случае можно использовать тип MEDIUMINT(5) UNSIGNED), и задается в формате: WHHMM, где W — номер дня недели (например на английский манер: 0 — вс, 1 — пн, и т.д., ну или можно нашу отечественную нумерацию дней недели выбрать: 0 — пн, 1 — вт, и т.д.), HH — часы, MM — минуты.

Например, организация X (id = 1) работает с 9:00 утра до 2:00 ночи, технический перерыв с 13:00 до 14:30. В нашей таблице, например, для понедельника это будет (если выбрана английския нумерация дней недели):
1 - 10900 - 11259
1 - 11431 - 20200

Поиск, какие организации работают например в среду в пять часов вечера, в такой таблице можно делать так:

SELECT id FROM organisations WHERE 31700 BETWEEN timefrom AND timeto;

Все, этого достаточно.
Но вот если в задачу добавятся еще и праздничные дни, когда те или иные организации не работают, или работают по специальному графику, понадобится заводить отдельную таблицу для исключений, и усложнять запрос.
Виталий К.
55 сообщений
#14 лет назад
tvv, отличное решение, спасибо.

Я так и сделаю,
только может вынести день недели в отдельный столбец
где будет 0-пн, 1-вт, ...., 6-вс, 7-пн-пт, 8-пн-вс ?
Вадим Т.
3240 сообщений
#14 лет назад
Цитата ("storier"):
только может вынести день недели в отдельный столбец
где будет 0-пн, 1-вт, ...., 6-вс, 7-пн-пт, 8-пн-вс ?

Не нужно, это избыточно.
И рекомендую использовать английский вариант: 0 — вс, 1 — пн, и т.д., так как тогда будет удобно пользоваться стандартными функциями для работы с датой/временем. Хотя это уже менее значимо.
Вячеслав С.
3 сообщения
#13 лет назад
Цитата ("tvv"):
Например, организация X (id = 1) работает с 9:00 утра до 2:00 ночи, технический перерыв с 13:00 до 14:30. В нашей таблице, например, для понедельника это будет (если выбрана английския нумерация дней недели):
1 - 10900 - 11259
1 - 11431 - 20200

Для данного примера надо делать 3 записи в таблице:
1 - 10900 - 11259
1 - 11431 - 12359
1 - 20000 - 20200

Потому что запрос:

SELECT id FROM organisations WHERE findtime BETWEEN timefrom AND timeto;

не всегда будет выдавать правильный результат.

Например, организация X (id = 1) в субботу работает с 9:00 утра до 2:00 ночи, технический перерыв с 13:00 до 14:30.
Если сделать 2 записи:
1 - 60900 - 61259
1 - 61431 - 00200

то запрос на поиск организаций, которые работают в 1:00 ночи в воскресенье (findtime = 00100) не выдаст нужный результат.

Если сделать 3 записи:
1 - 60900 - 61259
1 - 61431 - 62359
1 - 00000 - 00200

тогда
SELECT id FROM organisations WHERE 00100 BETWEEN timefrom AND timeto;

отработает правильно
Николай М.
1895 сообщений
#13 лет назад
Мы когда-то делали так,
разделили неделю на минуты, тоесть получилось у нас 0..7*24*60=10080
таким образом пишем время, где в 1 величине полностью хранится времья за период (в минутах, в данном случаи дня недели), с интервалом в 1 мин., можно и в 5 мин., тогда получится 0..7*24*12=2016
работать с таким подходом достаточно просто, запроси принимают вида с простой конструкцией beetween, тоесть работать будет очень быстро

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

вообщето я рекомендую почитать про cross-таблицы, их еще называют "шахматки"
Вячеслав С.
3 сообщения
#13 лет назад
Цитата ("MMM_Corp"):
Мы когда-то делали так,
разделили неделю на минуты, тоесть получилось у нас 0..7*24*60=10080

в вашем подходе, также, как и при хранении времени работы заведения в формате WHHMM, есть один небольшой недостаток, на который я пытался указать в предыдущем посте:
в случае, если график работы переходит через сутки (например, с 17:00 до 02:00), то может возникнуть ситуация, что будет переход не только через сутки, но и через неделю.
В английской нумерации недели: суббота - 6, воскресенье - 0. Если учреждение работает в субботу с 17:00 до 02:00, то при записи этого интервала в БД его надо разбить на 2 записи:
1. с 17:00 субботы до 23:59 субботы
2. с 00:00 воскресенья до 02:00 воскресенья
иначе конструкция beetween не отработает, т.к. timefrom будет больше timeto и в вашем подходе тоже.

Об этом почему то никто не упоминает...