/ /営業時間/休日の保存 - sql、schema、plpgsql

営業時間/休日の保存 - 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時まで開いている可能性があります。その時点で、以前のレストランをチェックする必要があります dow.

問題をもっと複雑にするために、私は休日に対処しなければなりません:

CREATE TABLE holidays (
"restaurant" integer NOT NULL REFERENCES restauraunts ON DELETE CASCADE,
"day" date NOT NULL
);

同じ問題を抱えているのは、レストランが15:30〜2:00に開いている場合、それは夜中から2時までブロックが閉鎖されていることを意味します。

私は頭を包むことができなかった。このために清潔でエレガントな解決策を見つけることができました(いくつかのばかげたものが出てきました)。私は散歩に戻り、それに戻ってくる必要があります - その間、私はあなたにそれに亀裂を入れるようにしました。

回答:

回答№1は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の場合は0

コメントをまとめるには:

1 - 一般的なクエリ構造を使用する この質問から

2 - あなたのテーブルにビットフラグを追加する ClosePastMidnight または OpenPastMidnight (どちらかがあなたの思考方法に最も適しています)は、近い将来翌日になることを示し、それに応じてロジックを調整します。


回答№3の場合は0

テーブルデザインに欠けている情報あなたが何を閉じて開放を意味するのかを明確にしようとすると明らかになります。 12時から2時など.2時間か14か?前提を作らなければ、それを解決する方法はありません。

間隔を使用する:

たとえば、レストランが午後1時30分から午前1時30分までの場合、now()がinbetweenであるかどうかを確認できます:

test=# select
now() > (now()::date || " 13:30")::timestamp
and now() < (now()::date || " 13:30")::timestamp + interval "12 hours";

?column?
----------
t
(1 row)

そうすれば出発ダウだけが重要となり、ラップアラウンドの問題は起こらないはずです。