我使用的是Rails 4.2和PostgreSQL 9.4。
我有基本用户,预订和事件架构。
我想返回一个用户列表和他们参加的最新活动,以及这个活动的日期/时间。
我创建了一个返回用户和最近事件时间的查询。但是我还需要返回 events.id 。
我的应用程序不允许用户使用相同的开始时间保留两个事件,但我感谢SQL对此没有任何了解,并认为结果中可能有多个事件。因此,我很高兴查询在假设的'平局的情况下随机返回适当的事件ID。 for events.starts_at。
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
预留表非常大,因此将整个集合加载到Rails并通过Ruby代码处理它是不可取的。如果可以的话,我想在SQL中执行整个查询。
我的基本模特:
User
has_many :reservations
Reservation
belongs_to :user
belongs_to :event
Event
belongs_to :company
has_many :reservations
答案 0 :(得分:1)
返回最新事件数据的通用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
两个“凡什么”的东西都应该是一样的。您所要做的就是将此构造调整到您的应用程序中。您可以考虑将查询放入存储过程中,然后从应用程序中调用该存储过程。
答案 1 :(得分:0)
我认为您的查询应首先关注以检索最近的预订。
SELECT MAX(`events.starts_at`),`events"."id`,`user_id` FROM `reservations` WHERE (reservations.state = 'attended')
然后加入用户和活动。
假设结果将包括每个用户和事件,检索所有用户和事件可能更有效,然后存储在由id键入的两个数组中。
这背后的逻辑不是单独查找db引擎对每个结果预留的用户和事件表,而是在单个查询中将它们全部都更有效。
SELECT * FROM Users' WHERE 1 ORDER BY
user_id`
SELECT * FROM Events' WHERE 1 ORDER BY
event_id`
我不熟悉Rails语法,因此不能给出确切的代码,但可以在PHP代码中使用它,结果只用一行代码放入数组。
while ($row = mysql_fetch_array($results, MYSQL_NUM)){users[$row(user_id)] = $row;}
然后在处理预订时,您将从阵列中获取用户和事件数据。
预订索引至关重要,可能值得分析。
可能的个人资料选择可能是包含和排除“有人参与”#39;在索引中。 events.starts_at应该是索引中的第一列,后跟user_id。但应分析对索引列顺序的分析。
您可能希望使用唯一索引来强制执行无重复的预订时间。