存储营业时间/假期

时间:2010-12-17 20:27:53

标签: sql schema plpgsql

您建议使用哪种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,这意味着它们也会在午夜到两个时间内关闭。

我无法为此寻找一个干净,优雅的解决方案(几个混乱的问题已经过去)。我需要去散步并回到它 - 同时,我想我会让你们抓住它。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

总结评论:

1 - 使用常规查询结构from this question.

2 - 为ClosePastMidnightOpenPastMidnight(最适合您的思维方式)添加一个位标记,表示将在下一个日历日关闭,并相应地调整您的逻辑。< / p>

答案 2 :(得分:0)

当您尝试消除关闭和打开的含义时,您的表格设计缺少信息。如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)

这样只有起始点很重要,你不应该有任何回转问题。