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 BY
user_id`
SELECT * 来自 Events' WHERE 1 ORDER BY
event_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.
您可能希望使用唯一索引来强制执行无重复预订时间。
我正在使用 Rails 4.2 和 PostgreSQL 9.4。
我有一个基本的用户、预订和事件架构。
我想要 return 用户列表和他们最近参加的活动,以及 date/time 这是在什么地方。
我创建了一个 return 用户和最近事件时间的查询。但是我也需要 return events.id。
我的应用程序不允许用户保留两个具有相同开始时间的事件,但我很感激 SQL 对此一无所知,并认为结果中可能有多个事件。因此,我很高兴在 events.starts_at.
的假设 'tie' 的情况下随机查询 return 适当的事件 IDUser.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 BY
user_id`
SELECT * 来自 Events' WHERE 1 ORDER BY
event_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.
您可能希望使用唯一索引来强制执行无重复预订时间。