Rails / SQL 查询查找最近的事件

Rails / SQL Query finding most recent Event

我正在使用 Rails 4.2 和 PostgreSQL 9.4。

我有一个基本的用户、预订和事件架构。

我想要 return 用户列表和他们最近参加的活动,以及 date/time 这是在什么地方。

我创建了一个 return 用户和最近事件时间的查询。但是我也需要 return events.id

我的应用程序不允许用户保留两个具有相同开始时间的事件,但我很感激 SQL 对此一无所知,并认为结果中可能有多个事件。因此,我很高兴在 events.starts_at.

的假设 'tie' 的情况下随机查询 return 适当的事件 ID

User.all.joins(reservations: :event) .select('users.*, max(events.starts_at)') .where('reservations.state = ?', "attended") .where('events.company_id = ?', 1) .group('users.id')

对应的SQL查询为: SELECT users.*, max(events.starts_at) FROM "users" INNER JOIN "reservations" ON "reservations"."user_id" = "users"."id" INNER JOIN "events" ON "events"."id" = "reservations"."event_id" WHERE (reservations.state = 'attended') AND (events.company_id = 1) GROUP BY users.id

保留 table 非常大,因此将整个集合加载到 Rails 并通过 Ruby 代码处理它是不可取的。如果可能的话,我想在 SQL 中执行整个查询。

我的基本型号:

User
has_many :reservations

Reservation
belongs_to :user
belongs_to :event

Event
belongs_to :company
has_many :reservations

最近事件的 returns 数据的通用 sql 如下所示:

select yourfields
from yourtables
join 
(select someField
, max(datetimefield) maxDateTime
from table1
where whatever
group by someField ) temp on table1.someField = temp.somefield
and table1.dateTimeField = maxDateTime
where whatever

这两个"where whatever"东西应该是一样的。您所要做的就是将此结构调整到您的应用程序中。您可能会考虑将查询放入一个存储过程,然后您可以从您的应用程序调用该存储过程。

我认为您的查询应该首先关注检索最近的预订。

SELECT MAX(`events.starts_at`),`events"."id`,`user_id` FROM `reservations`  WHERE (reservations.state = 'attended') 

然后加入用户和活动。

假设结果将包括每个用户和事件,那么检索所有用户和事件并将其存储在两个由 id 键控的数组中可能更有效。

其背后的逻辑不是单独查找用户和事件 table 数据库引擎针对每个结果保留,在单个查询中获取它们会更有效。

SELECT * 来自 Users' WHERE 1 ORDER BYuser_id`

SELECT * 来自 Events' WHERE 1 ORDER BYevent_id`

我不熟悉 Rails 语法,所以无法给出确切的代码,但可以显示在 PHP 代码中使用它,结果用一行代码放入数组中。

while ($row = mysql_fetch_array($results, MYSQL_NUM)){users[$row(user_id)] = $row;}

然后在处理预订时,您会从数组中获取用户和事件数据。

预订索引很重要,可能值得分析。

可能的配置文件选择可能是在索引中包含和排除 'attended'。 events.starts_at 应该是索引中的第一列,然后是 user_id。但是profiling Index的column order应该profile.

您可能希望使用唯一索引来强制执行无重复预订时间。