我有一个表,其中包含一对表示时间跨度的时间戳.这些行的范围是用户标识,每个用户可以有一个或多个与之关联的行.
此数据是从抽象的“可用性”表单生成的,该表单表示用户何时在一周内可用.我需要输入一系列时间范围作为查询,并返回表中所有行匹配的所有用户ID.
鉴于此表:
CREATE TABLE "public"."availability" ( "id" int4 NOT NULL,"user_id" int4,"starts_at" timestamp(6),"ends_at" timestamp(6),PRIMARY KEY ("id") ) WITH (OIDS=FALSE)
而这个数据:
User #1 is available Mon-Tue between 08:00 and 17:00 +----+---------+---------------------+---------------------+ | id | user_id | starts_at | ends_at | +----+---------+---------------------+---------------------+ | 1 | 1 | 2013-03-18 08:00:00 | 2013-03-18 17:00:00 | +----+---------+---------------------+---------------------+ | 2 | 1 | 2013-03-19 08:00:00 | 2013-03-19 17:00:00 | +----+---------+---------------------+---------------------+ User #2 is available Sun-Sat all day +----+---------+---------------------+---------------------+ | 3 | 2 | 2013-03-17 00:00:00 | 2013-03-23 23:59:59 | +----+---------+---------------------+---------------------+ User #3 is available Wed between 06:00 and 18:00 +----+---------+---------------------+---------------------+ | 4 | 3 | 2013-03-20 06:00:00 | 2013-03-20 18:00:00 | +----+---------+---------------------+---------------------+
我可以轻松选择可用于任何给定时间戳的用户:
SELECT * FROM "public"."availability" WHERE ('2013-03-19 08:35:00' BETWEEN starts_at AND ends_at AND '2013-03-19 18:25:00' BETWEEN starts_at AND ends_at) OR ('2013-03-20 12:00:00' BETWEEN starts_at AND ends_at AND '2013-03-20 18:00:00' BETWEEN starts_at AND ends_at); +----+---------+---------------------+---------------------+ | id | user_id | starts_at | ends_at | +----+---------+---------------------+---------------------+ | 3 | 2 | 2013-03-17 00:00:00 | 2013-03-23 23:59:59 | +----+---------+---------------------+---------------------+ | 4 | 3 | 2013-03-20 06:00:00 | 2013-03-20 18:00:00 | +----+---------+---------------------+---------------------+
但我真正需要的是能够查询多个时间盘并仅返回匹配所有条件的user_ids.
查询:2013-03-17 10:00:00-2013-03-17 16:00:00,2013-03-23 10:00:00-2013-03-23 16:00:00应该返回:
+----+---------+---------------------+---------------------+ | id | user_id | starts_at | ends_at | +----+---------+---------------------+---------------------+ | 3 | 2 | 2013-03-17 00:00:00 | 2013-03-23 23:59:59 | +----+---------+---------------------+---------------------+
查询:2013-03-18 09:00:00-2013-03-18 16:00:00,2013-03-19 08:00:00-2013-03-19 15:45:00应该返回:
+----+---------+---------------------+---------------------+ | id | user_id | starts_at | ends_at | +----+---------+---------------------+---------------------+ | 1 | 1 | 2013-03-18 08:00:00 | 2013-03-18 17:00:00 | +----+---------+---------------------+---------------------+ | 2 | 1 | 2013-03-19 08:00:00 | 2013-03-19 17:00:00 | +----+---------+---------------------+---------------------+ | 3 | 2 | 2013-03-17 00:00:00 | 2013-03-23 23:59:59 | +----+---------+---------------------+---------------------+
查询:2013-03-18 07:00:00-2013-03-18 18:00:00应该什么都不返回.
解决方法
SQL Fiddle
这会将boolean强制转换为整数0或1.
select a.* from availability a inner join ( select user_id,sum ( ('2013-03-18 09:00:00' between starts_at and ends_at and '2013-03-18 16:00:00' between starts_at and ends_at )::integer + ('2013-03-19 08:00:00' between starts_at and ends_at and '2013-03-19 15:45:00' between starts_at and ends_at )::integer ) period from availability group by user_id ) s on a.user_id = s.user_id where period >= 2
将where条件更改为要匹配的句点数.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。