我正在尝试改进以下计划的SQL:
它看起来像这样:
- @users.each do |user|
- @dates.each do |date|
%td
- Booking.where(user: user, date: date).each do |booking|
= booking.shift_time
@users
由表格中的用户组成。
@dates
由日期组成:周初 - >一周结束
显然这段代码很糟糕,因为每个日期,预订和用户都会触发查询。 拥有多个用户需要很长时间才能加载页面。
如何改进此查询?是否可以通过使用一个(大)查询从数据库中获取所有这些数据?如果这有任何区别,我会使用PostgreSQL。
一个建议是我按日期在@dates
和组之间进行所有预订。但这意味着我必须用NULL
值替换特定日期和用户的不存在的预订,但我不知道我将如何做到这一点。
这是sql输出:
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-09'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-10'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-11'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-12'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-13'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-14'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 1 AND "bookings"."date" = '2015-03-15'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-09'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-10'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-11'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-12'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-13'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-14'
SELECT "bookings".* FROM "bookings" WHERE "bookings"."user_id" = 2 AND "bookings"."date" = '2015-03-15'
答案 0 :(得分:1)
您可以执行以下操作:
# controller
def your_action
@users = User.some_scope
@dates = some_logic_to_return_array_of_dates
bookings = Booking.where(user_id: @users.map(&:id), date: @dates)
# the above will select all Booking record having user_id in the selected users' ids AND date IN the selected range/array of dates
@bookings_by_date = bookings.group_by(&:date)
# group results like
# {
# <Date> => [<Booking>, <Booking>],
# <Date2> => [<Booking>]
# }
end
然后在你看来:
# view
- @users.each do |user|
- @dates.each do |date|
%td
- todays_bookings = @bookings_by_date[date].presence || []
- todays_bookings.select{ |booking| booking.user == user }.each do |booking|
= booking.shift_time
答案 1 :(得分:0)
# action
@dates = start_date..end_date
@users = User.some_scope.includes(:bookings)
# view
- @users.each do |user|
%tr
- @dates.each do |date|
%td
= user.bookings.select{|booking| booking.date == date}.each do |user_booking|
= user_booking
这应该只打两次数据库(2个用户查询,1个用于预订)