postgresql - 如何获取商店的交易时间
问题描述
我希望得到一家商店的交易时间。我的模式代表了营业时间,以及商店营业的持续时间,这很琐碎。提供了一个覆盖表来存储与标准交易时间不同的日期,或者如果商店在给定的一天或几天关闭。例如:圣诞节,或周末等。
我怎样才能显示当前星期(周日至周六)的相关交易时间,并覆盖每一天的时间?
我尝试过的架构和一些 SQL 如下:
CREATE TABLE shop(
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
INSERT INTO shop(id, name) VALUES (1, 'Empire');
INSERT INTO shop(id, name) VALUES (2, 'Dodgey Joes');
CREATE TABLE trading_hours(
id SERIAL PRIMARY KEY,
time_open TIME NOT NULL,
duration INTEGER NOT NULL, --In minutes
day_of_week INTEGER NOT NULL,
shop_id INTEGER REFERENCES shop(id)
);
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (1, '6:00', 720, 0, 1); -- sun 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (2, '6:10', 720, 1, 1); -- mon 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (3, '6:20', 720, 2, 1); -- tue 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (4, '6:30', 480, 3, 1); -- wed 8 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (5, '6:00', 720, 4, 1); -- thur 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (6, '6:00', 240, 5, 1); -- fri 4 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (7, '23:00', 240, 5, 1);-- fri 4 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (8, '6:00', 1200, 6, 1); -- sat 20 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (9, '7:00', 720, 0, 2); -- sun 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (10, '7:10', 720, 1, 2); -- mon 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (11, '7:20', 480, 2, 2); -- tue 8 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (12, '7:30', 510, 3, 2); -- wed 8.5 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (13, '7:00', 720, 4, 2); -- thur 12 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (14, '7:00', 240, 5, 2); -- fri 4 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (15, '12:00', 360, 5, 2);-- fri 6 hours
INSERT INTO trading_hours(id, time_open, duration, day_of_week, shop_id) VALUES (16, '7:00', 1200, 6, 2); -- sat 20 hours
CREATE TABLE other_hours(
id SERIAL PRIMARY KEY,
time_open TIME NOT NULL,
duration INTEGER NOT NULL, --In minutes
day_of_week INTEGER NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
closed BOOLEAN NOT NULL,
shop_id INTEGER REFERENCES shop(id)
);
-- shop 1 closed xmas day
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (1, '00:00', 0, 3, '2019-12-25', '2019-12-25', true, 1);
-- shop 1 closed every tuesday in January
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (2, '00:00', 0, 2, '2020-01-01', '2020-01-31', true, 1);
--shop 2 closed new years day
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (3, '00:00', 0, 3, '2020-01-01', '2020-01-01', true, 2);
--shop two closed Jan 10 to Feb 10
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (4, '00:00', 0, 0, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (5, '00:00', 0, 1, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (6, '00:00', 0, 2, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (7, '00:00', 0, 3, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (8, '00:00', 0, 4, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (9, '00:00', 0, 5, '2020-01-01', '2020-01-01', true, 2);
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (10, '00:00', 0, 6, '2020-01-01', '2020-01-01', true, 2);
-- shop 1 open 11:00am on Jan 2
INSERT INTO other_hours(id, time_open, duration, day_of_week, start_date, end_date, closed, shop_id) VALUES (11, '11:00', 420, 4, '2020-01-02', '2020-01-02', true, 1);
还有一些 SQL:
elect th.day_of_week,
case th.day_of_week
WHEN 0 THEN 'Sun'
WHEN 1 THEN 'Mon'
WHEN 2 THEN 'Tue'
WHEN 3 THEN 'Wed'
WHEN 4 THEN 'Thu'
WHEN 5 THEN 'Fri'
WHEN 6 THEN 'Sat'
end AS day_name,
sh.name, th.time_open,
th.time_open +(th.duration::text||' minute')::INTERVAL AS time_close,
oh.time_open AS other_time_open,
oh.time_open +(oh.duration::text||' minute')::INTERVAL AS other_time_close,
case
WHEN DATE(NOW()) >= oh.start_date AND DATE(NOW()) <= oh.end_date
THEN oh.time_open
ELSE th.time_open
END AS kev_open_time
FROM trading_hours th
JOIN shop sh ON th.shop_id=sh.id
LEFT JOIN other_hours oh ON th.shop_id=oh.shop_id AND oh.day_of_week=th.day_of_week
ORDER BY sh.name, th.day_of_week, th.time_open
;
解决方案
正如我在评论中提到的,WHEN DATE(NOW()) >= oh.start_date AND DATE(NOW()) <= oh.end_date
对我来说似乎是错误的。DATE(NOW())
应该是一周中特定日期的日期。
我想我会从为本周的日子生成日期开始。就像是:
SELECT date, extract(dow from date) as day_of_week
FROM (
SELECT current_date + series AS date FROM generate_series(1,7) AS series
) AS "dates"
或者更好的是,将其与工作日对齐:
SELECT date, extract(dow from date) as day_of_week
FROM (
SELECT current_date - extract(dow from current_date)::Int + series AS date
FROM generate_series(0,6) AS series
) AS "dates"
这使:
date | day_of_week
------------+-------------
2019-12-22 | 0
2019-12-23 | 1
2019-12-24 | 2
2019-12-25 | 3
2019-12-26 | 4
2019-12-27 | 5
2019-12-28 | 6
现在您可以将它与您的查询结合使用,dates.date
而不是DATE(NOW())
:
SELECT
dates.date AS date,
to_char(dates.date, 'day') AS day_of_week,
sh.name,
COALESCE(oh.time_open, th.time_open) AS time_open,
CASE
WHEN oh.time_open IS NOT NULL
THEN oh.time_open + (oh.duration::text||' minute')::INTERVAL
ELSE th.time_open + (th.duration::text||' minute')::INTERVAL
END AS time_close
FROM (
SELECT current_date - extract(dow from current_date)::Int + series AS date
FROM generate_series(0,6) AS series
) AS dates
LEFT JOIN trading_hours th ON th.day_of_week = extract(dow from dates.date)
LEFT JOIN other_hours oh ON
th.shop_id=oh.shop_id AND
oh.day_of_week=th.day_of_week AND
dates.date >= oh.start_date AND
dates.date <= oh.end_date
JOIN shop sh ON th.shop_id=sh.id
ORDER BY sh.name, dates.date, time_open;
推荐阅读
- c# - 如何在类中将内部数据公开为只读?
- operating-system - 通常使用什么数据结构来实现框架表?
- node.js - Socketio 不会从托管站点连接到 droplet
- java - 如何将 Java 对象的实例从 Python 传递到 Java 应用程序
- macos - 将 MacOS App 按键转发到 iOS 模拟器
- android - 在后台杀死 android 应用程序后,getServerAuthCode 始终返回 null
- spring - 如何配置我的 logback 系统,以便它可以在基于时间的滚动周期完成后立即创建日志文件?
- smartsheet-api - 如何检索用户管理报告?
- sql - 如何合并hive中的行?
- python - Python:将键的字典:列表转换为字典:键/值对