Sql 用户事件ORM模型的阻止日期的实现
延续 我有一个应用程序(RubyonRails、ActiveRecord、Postgresql),它使用用户表、日期表和事件表来跟踪用户及其事件以及这些事件发生的日期。事件有许多日期,用户可以通过不同的表登录事件 我在这里研究的功能是让用户能够阻止某些日期,以便我以后可以找到1)没有阻止X[]中任何日期的用户,以及2)从用户一侧,所有不包含用户阻止的任何日期的事件 我目前使用的是一种基本方法,日期存储为用户、事件和运算符的简单字符串:Sql 用户事件ORM模型的阻止日期的实现,sql,ruby-on-rails,postgresql,date,activerecord,Sql,Ruby On Rails,Postgresql,Date,Activerecord,延续 我有一个应用程序(RubyonRails、ActiveRecord、Postgresql),它使用用户表、日期表和事件表来跟踪用户及其事件以及这些事件发生的日期。事件有许多日期,用户可以通过不同的表登录事件 我在这里研究的功能是让用户能够阻止某些日期,以便我以后可以找到1)没有阻止X[]中任何日期的用户,以及2)从用户一侧,所有不包含用户阻止的任何日期的事件 我目前使用的是一种基本方法,日期存储为用户、事件和运算符的简单字符串: User.where.not("string_to_arra
User.where.not("string_to_array(blocked_dates, ',') && string_to_array(?, ',')", "date1,date2...")
我想知道是否有任何面向数据库的方法可以解决这个问题,它们的性能比比较阵列重叠要好
Postgres版本:psql(PostgreSQL)9.4.5
表基数:
用户-事件:一对多(如果用户是status manager)
用户-事件:通过名为“邀请”的不同表进行多对多访问(如果用户是客户机状态)
事件-事件日期:一对多
来自\d个用户的语句
来自\d事件的语句
来自\d事件\u日期的语句
来自新字段的语句\d已阻止\u日期\u期间
这是我选择的解决方案。诀窍是使用
左外部联接
(ruby命令eager\u load)为用户和阻塞的\u date\u periods表,并包括那些在联接表中的start\u date字段为NULL的用户,这显然是因为他们没有任何与自己关联的阻塞日期对象。我使用的查询:
User.eager_load(:blocked_date_periods).
where("blocked_date_periods.start_date is null OR
not tsrange(
blocked_date_periods.start_date - '00:59:59'::interval,
blocked_date_periods.end_date + '00:59:59'::interval
) @> ?::timestamp",
Date.parse(DATE_STRING)).count
我不得不从开始日期和结束日期中加减1小时,因为出于某种原因,查询不希望包含确切的结束日期,因此2015年12月26日不包括在2015年12月22日至2015年12月16日期间,原因我尚不清楚
出于某种原因,我不喜欢这种解决方案,我想知道是否有比我现有的查询更好更快的查询。请提供基本信息。在psql中完成
CREATE TABLE
语句或使用\d tbl
获得的内容。您的Postgres版本和基数。这可能是iCalendar RRULEs和EXDATEs的一个很好的用法。请参见我在当前已编辑的表上发布的特定信息。更新,似乎我需要以日期周期的形式输入阻止日期,包括开始日期和结束日期。问题是,如果我有blocked date period对象(请参阅文章中的信息),那么对于给定用户的阻止日期的用户,我将通过什么查询来获取其日期不属于这些开始-结束时间段的事件?
id | integer | not null default nextval('events_id_seq'::regclass)
title | character varying(255) |
description | text |
user_id | integer (this refers to another type of user, capable of creating events, not the type of user we are referring to here) |
project_status | character varying(255) | default 'create_project'::character varying
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
due_time | timestamp without time zone |
...
and other fields such as address, referrer number...
id | integer | not null default nextval('event_dates_id_seq'::regclass)
title | character varying(255) |
event_id | integer |
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
date | character varying(255) (I need to explicitly store a string value) |
formatted_date | timestamp without time zone (String value is converted to the timestamp on save) |
Indexes:
"event_dates_pkey" PRIMARY KEY, btree (id)
"index_event_dates_on_event_id" btree (event_id)
id | integer | not null default nextval('blocked_date_periods_id_seq'::regclass)
user_id | integer |
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
start_date | timestamp without time zone |
end_date | timestamp without time zone |
User.eager_load(:blocked_date_periods).
where("blocked_date_periods.start_date is null OR
not tsrange(
blocked_date_periods.start_date - '00:59:59'::interval,
blocked_date_periods.end_date + '00:59:59'::interval
) @> ?::timestamp",
Date.parse(DATE_STRING)).count