у меня есть таблица, которая перечисляет часы работы ресторанов. столбцы являются идентификатором, eateries_id, day_of_week, start_time, и end_time. каждая столовая представлена в таблице многократно, потому что существует отдельная запись в течение каждого дня. дополнительную информацию см. в этом предыдущем вопросе: определите, открыт ли ресторан теперь (как визг, делает), использование базы данных, php, js
я задаюсь вопросом теперь, как взять данные из этой таблицы и распечатать его в человекочитаемом формате. например, вместо того, чтобы говорить "M 1-3, T 1-3, W 1-3, Th 1-3, F 1-8" я хотел бы сказать "M-Th 1-3, F 1-8". точно так же я хочу "M 1-3, 5-8" вместо "M 1-3, M 5-8". как я мог бы сделать это без метода грубой силы многочисленных если операторы?
спасибо.
Вы хотите объединить кучу интервалов для каждого дня. Придерживайтесь 24-часового формата (на самом деле сначала конвертируйте его в секунды, я думаю), пока вам не придется конвертировать его в более дружественный человеку формат.
http://pyinterval.googlecode.com/svn/trunk/html/index.html
Проблема в том, что когда вы допускаете секунды ... ресторан, который закрывается на 1 секунду раньше, будет пропущен :( Возможно, вам нужно допускать 15 или 5 -минутные приращения. Если нужно, округлите данные в DB. Итак, подход следующий: используя структуру данных интервалов, объедините все интервалы для данного дня вместе. Теперь переверните словарь. Вместо того чтобы сопоставлять дни с интервалами, сопоставьте интервалы с днями. Теперь найдите способ разумно представить эти группы дней. Например, set(1,2,3)
может быть отображен как "M-W", поэтому я бы предложил: для каждого мощного набора множества {1,2,3,4,5,6,7}
(или {1,2,3,4,5}
) найдите наилучшее человеческое представление (вручную). Теперь закодируйте эту логику - запишите ее в словарь, который сопоставляет отсортированную строку (это важно), такую как "1235", с человеческим представлением, таким как "M-W,F". Отображать 1-3, 5-8 легко, если вы работаете с интервальным объектом, как описано в ссылке выше. Удачи! Дайте мне знать, с какими проблемами вы столкнулись.
EDIT:
Это не лучший пример, который у них есть (не показывает объединение перекрывающихся интервалов), но вам важен оператор "|"
unioned:
>>> interval[1, 4] | interval[2, 5]
interval([1.0, 5.0])
>>> interval[1, 2] | interval[4, 5]
interval([1.0, 2.0], [4.0, 5.0])
Вы можете просто реализовать этот класс самостоятельно, но это может быть чревато ошибками.
Решил попробовать это.
Тестовая таблица
CREATE TABLE `opening_hours` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`eateries_id` int(11) DEFAULT NULL,
`day_of_week` int(11) DEFAULT NULL,
`start_time` time DEFAULT NULL,
`end_time` time DEFAULT NULL,
PRIMARY KEY (`id`)
)
Тестовые данные
INSERT INTO `test`.`opening_hours`
(
`eateries_id`,
`day_of_week`,
`start_time`,
`end_time`)
SELECT 2 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 1 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 2 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 2 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 2 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00' as end_time
union all
SELECT 3 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 3 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all
SELECT 3 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all
SELECT 3 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00' as end_time
Определение вида для объединения часов работы по дням
CREATE VIEW `test`.`groupedhours`
AS
select `test`.`opening_hours`.`eateries_id` AS `eateries_id`,
`test`.`opening_hours`.`day_of_week` AS `day_of_week`,
group_concat(concat(date_format(`test`.`opening_hours`.`start_time`,'%l'),' - ',date_format(`test`.`opening_hours`.`end_time`,'%l %p')) order by `test`.`opening_hours`.`start_time` ASC separator ', ') AS `OpeningHours`
from `test`.`opening_hours`
group by `test`.`opening_hours`.`eateries_id`,`test`.`opening_hours`.`day_of_week`
Запрос для поиска "островов" смежных дней с одинаковыми часами работы (на основе одного из примеров Ицика Бен Гана)
SET @rownum = NULL;
SET @rownum2 = NULL;
SELECT S.eateries_id,
concat(CASE WHEN
S.day_of_week <> E.day_of_week
THEN
CONCAT(CASE S.day_of_week
WHEN 1 THEN 'Su'
WHEN 2 THEN 'Mo'
WHEN 3 THEN 'Tu'
WHEN 4 THEN 'We'
WHEN 5 THEN 'Th'
WHEN 6 THEN 'Fr'
WHEN 7 THEN 'Sa'
End, ' - ')
ELSE ''
END,
CASE E.day_of_week
WHEN 1 THEN 'Su'
WHEN 2 THEN 'Mo'
WHEN 3 THEN 'Tu'
WHEN 4 THEN 'We'
WHEN 5 THEN 'Th'
WHEN 6 THEN 'Fr'
WHEN 7 THEN 'Sa'
End, ' ', S.OpeningHours) AS `Range`
FROM (
SELECT
A.day_of_week,
@rownum := IFNULL(@rownum, 0) + 1 AS rownum,
A.eateries_id,
A.OpeningHours
FROM `test`.`groupedhours` as A
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B
WHERE A.eateries_id = B.eateries_id
AND A.OpeningHours = B.OpeningHours
AND B.day_of_week = A.day_of_week -1)
ORDER BY eateries_id,day_of_week) AS S
JOIN (
SELECT
A.day_of_week,
@rownum2 := IFNULL(@rownum2, 0) + 1 AS rownum,
A.eateries_id,
A.OpeningHours
FROM `test`.`groupedhours` as A
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B
WHERE A.eateries_id = B.eateries_id
AND A.OpeningHours = B.OpeningHours
AND B.day_of_week = A.day_of_week + 1)
ORDER BY eateries_id,day_of_week) AS E
ON S.eateries_id = E.eateries_id AND
S.OpeningHours = S.OpeningHours AND
S.rownum = E.rownum
Результаты
eateries_id Range
2 Su - Mo 1 - 3 PM, 5 - 8 PM
2 Tu 1 - 3 PM
2 We 1 - 8 PM
2 Th 1 - 3 PM
2 Fr 1 - 8 PM
2 Sa 1 - 9 PM
3 Su - Tu 1 - 3 PM
3 We 1 - 8 PM
3 Th 1 - 3 PM
3 Fr 1 - 8 PM
3 Sa 1 - 9 PM