存储营业时间/节假日
Posted
技术标签:
【中文标题】存储营业时间/节假日【英文标题】:Storing Open Hours/Holidays 【发布时间】:2010-12-17 20:27:53 【问题描述】:您建议使用哪种 SQL 模式来存储营业时间和节假日,以及使用哪种查询来检查餐厅是否营业?现在我有这个:
CREATE TABLE hours (
"restaurant" integer NOT NULL REFERENCES restaurants ON DELETE CASCADE,
"dow" integer NOT NULL,
"open" time NOT NULL,
"close" time NOT NULL
);
CREATE FUNCTION is_open(r integer) RETURNS boolean AS $$
DECLARE
h record;
t time;
BEGIN
SELECT open, close INTO h
FROM hours WHERE restaurant = r AND dow = EXTRACT(dow FROM now());
IF NOT FOUND THEN
RETURN false;
END IF;
t := current_time;
IF h.close <= h.open THEN
RETURN (t < h.close OR t > h.open);
ELSE
RETURN (t > h.open AND t < h.close);
END IF;
END;
$$ LANGUAGE plpgsql;
但这并没有真正起作用,因为例如,一家餐厅可能营业到凌晨 2:00,此时我需要检查之前的 dow
。
为了让事情变得更复杂,我必须处理假期:
CREATE TABLE holidays (
"restaurant" integer NOT NULL REFERENCES restauraunts ON DELETE CASCADE,
"day" date NOT NULL
);
这有同样的问题 - 如果餐厅从 15:30 到 2:00 营业,这意味着他们也从午夜到两点关闭。
我一直无法找到一个干净、优雅的解决方案来解决这个问题(一些混乱的解决方案来了又去)。我需要出去散散步,然后再回来——同时,我想我会让你们试一试。
【问题讨论】:
昨天的重复问题: ***.com/questions/4464898/… 没有回答我的问题,那就是如何处理营业到午夜的商店 添加位字段ClosePastMidnight
,如果设置为1
,则添加一天。
+1 对 JNK 的建议;另一种方法是检查close
是否在open
之前(如果是,则商店在午夜之后营业)。
打开时间的长短是正确解决问题的唯一方法
【参考方案1】:
回答我自己的问题似乎有点错误,但我发现了一些似乎有效的方法,尽管它很混乱:
CREATE FUNCTION is_open(r integer) RETURNS boolean AS $$
DECLARE
t time;
yesterday date;
dow_today integer;
dow_yesterday integer;
BEGIN
t := current_time;
yesterday := current_date - 1;
dow_today := EXTRACT(dow FROM current_date);
dow_yesterday := EXTRACT(dow FROM yesterday);
PERFORM * FROM hours
WHERE restaurant = r AND ((
dow = dow_today
AND NOT EXISTS(
SELECT * FROM holidays
WHERE restaurant = r AND day = current_date
) AND (
(open < close AND t > open AND t < close)
OR (open >= close AND t > open)
)
) OR (
open >= close AND dow = dow_yesterday
AND NOT EXISTS(
SELECT * FROM holidays
WHERE restaurant = r AND day = yesterday
) AND t < close
));
RETURN FOUND;
END;
$$ LANGUAGE plpgsql;
【讨论】:
【参考方案2】:总结一下cmets:
1 - 使用通用查询结构from this question.
2 - 为ClosePastMidnight
或OpenPastMidnight
(以最适合您的思维方式的方式)在您的表格中添加一个位标志,表明下一个日历日关闭,并相应地调整您的逻辑。
【讨论】:
感谢您的帮助,但请参阅我上面的评论【参考方案3】:您的表格设计缺少信息,当您尝试消除关闭和打开的含义时,这些信息会变得很明显。比如 12 比 2。那是 2 小时还是 14 小时?不做假设就没有办法解决。
使用间隔:
例如,如果您的餐厅从下午 1:30 到凌晨 1:30,这可以检查 now() 是否介于两者之间:
test=# select
now() > (now()::date || ' 13:30')::timestamp
and now() < (now()::date || ' 13:30')::timestamp + interval '12 hours';
?column?
----------
t
(1 row)
这样只有起点很重要,你不应该有任何环绕问题。
【讨论】:
那是什么符号?我以前从未见过now()::date
另外,这仍然存在 current_date 或 now() 无法匹配hours
表中的dow
列的问题。
检查两次即可。在我的示例中,您构建了正确的日期。选择道琼斯指数。将其减回一个。你能用 now() 构造一个区间吗?用当前的星期几再次检查。
12:00 到 2:00?那只能表示 14 小时,除非您的意思是 12:00 到 14:00... 没有歧义,因为时间是 24 小时格式的。以上是关于存储营业时间/节假日的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ1588][HNOI2002]营业额统计 无旋Treap