使用php从数据库表以可读格式打印餐厅营业时间
我有一张列有餐馆营业时间的桌子。列为id、eateries、day、start和end。每个餐厅在表中都有多次表示,因为每天都有一个单独的条目。有关更多详细信息,请参见上一个问题: 我现在想知道如何从这个表中获取数据,并以人类可读的格式打印出来。例如,我想说的不是“m1-3,t1-3,w1-3,th1-3,f1-8”,而是“m1-th1-3,f1-8”。类似地,我想要“m1-3,5-8”而不是“m1-3,m5-8”。如果没有大量if语句的蛮力方法,我怎么做呢使用php从数据库表以可读格式打印餐厅营业时间,php,sql,database,time,Php,Sql,Database,Time,我有一张列有餐馆营业时间的桌子。列为id、eateries、day、start和end。每个餐厅在表中都有多次表示,因为每天都有一个单独的条目。有关更多详细信息,请参见上一个问题: 我现在想知道如何从这个表中获取数据,并以人类可读的格式打印出来。例如,我想说的不是“m1-3,t1-3,w1-3,th1-3,f1-8”,而是“m1-th1-3,f1-8”。类似地,我想要“m1-3,5-8”而不是“m1-3,m5-8”。如果没有大量if语句的蛮力方法,我怎么做呢 谢谢。我想我会在这里狂欢一下 试验
谢谢。我想我会在这里狂欢一下 试验台
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`
查询以查找连续几天中开放时间相同的“岛屿”(基于伊兹克·本·甘的查询)
您希望为每天合并一组时间间隔。坚持使用24小时格式(我想实际上是先将其转换为秒),直到您必须将其转换为更人性化的格式 问题是当你允许几秒钟。。。提前一秒关闭的餐厅将被错过:(可能您需要允许15或5分钟的增量。如果有必要,请将数据舍入到DB中。因此,方法是:使用间隔数据结构,将给定日期的所有间隔合并在一起。现在反转字典。而不是将天映射到间隔,而是将间隔映射到天。现在找到一种智能地表示这些天组的方法。Fo例如,
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就很容易了。祝您好运!让我知道您遇到了什么问题
编辑:
这不是它们的最佳示例(不显示重叠间隔的并集),但您关心的是“|”运算符
您可以自己实现这个类,但它可能容易出现bug。它是如何存储在db中的“m1-3”的?还是时间戳?这是一个有趣的问题…我将尝试思考一下。它确实让我想起了一些电路简化,包括卡诺图:)我假设您关心高级方法,并且可以处理与您的精确表不匹配的答案。顺便问一下,是否只允许整小时?最早可能的小时和最晚可能的小时是什么时候?我将首先创建一个哈希表,将一天映射到小时,例如
{'M':set(1,2,3,5,6,7,8),'T':set(1,2,3)}
或{'M':'yyyyyyy'}
(指示是否每小时(此处从1开始))是可用的。这是确定哪两天有相同的时间表的第一步,也是计算和简化开放时间联盟的第一步。为什么在您的示例中所有的时间都以1开始?这是一家晚餐厅吗?您关心24小时制吗?您希望AM和PM在其中吗?是否允许半小时增量?回答问题:时间以时间格式存储,如12:34:05。日期以整数形式存储在单独的列中(例如,2代表星期一)。允许任何时间到秒,尽管我99.9%确信没有餐厅的营业时间会涉及秒:)。最早的时间是00:00:00,最晚的时间是23:59:59,所以是24小时格式。当我为用户打印时间时,我希望使用am/pm,尽管在我计算出剩余时间后,这种转换应该不会很困难。高级方法很好,我只是不知道从哪里开始解决这个问题!MySQL。这就是你要问的,对吧?这很有趣。我的意见是,SQL应该让您快速获得数据,因为这是它最擅长的。我认为最好用更高级的语言来按摩它。您的SQL令人印象深刻。这里我假设Mon=1,Tue=2。。。Sun=7,因为这是一些国家的惯例——一周从周一开始,周日结束。我想我明白你的意思。。不过,难道我不需要硬编码一百多天的组合吗?不完全是,2^5=32;2^7=128:)但是,这些是可以生成的。
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
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])