我使用postgres在rails 5上,我有一个用户表和一个报告表。用户有很多报告,这些报告需要每天创建。我想获取所有尚未归档但尚未完成报告的用户,并显示昨天的报告说明(如果有)。
以下是模型:
用户模型
# == Schema Information
#
# Table name: users
#
# id :bigint(8) not null, primary key
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# archived :boolean default(FALSE)
#
class User < ApplicationRecord
has_many :reports
end
报告模型
# == Schema Information
#
# Table name: reports
#
# id :bigint(8) not null, primary key
# notes :text
# created_at :datetime not null
# updated_at :datetime not null
# user_id :bigint(8)
#
class Report < ApplicationRecord
belongd_to :user
end
以下是我希望从此查询中获得的示例:
用户表
------------------------------------------------------------------------------------
| id | name | archived | created_at | updated_at |
------------------------------------------------------------------------------------
| 1 | Jonn | false | 2018-05-11 00:01:36.124999 | 2018-05-11 00:01:36.124999 |
------------------------------------------------------------------------------------
| 2 | Sam | false | 2018-05-11 00:01:36.124999 | 2018-05-11 00:01:36.124999 |
------------------------------------------------------------------------------------
| 3 | Ashley | true | 2018-05-11 00:01:36.124999 | 2018-05-11 00:01:36.124999 |
------------------------------------------------------------------------------------
报告表(想象一下这个报告是昨天)
--------------------------------------------------------------------------------------
| id | user_id | notes | created_at | updated_at |
--------------------------------------------------------------------------------------
| 1 | 1 | Nothing | 2018-06-13 16:32:05.139284 | 2018-06-13 16:32:05.139284 |
--------------------------------------------------------------------------------------
欲望输出:
-------------------------------------------------------------------------------------------------------
| id | name | archived | created_at | updated_at | yesterdays_notes |
-------------------------------------------------------------------------------------------------------
| 1 | Jonn | false | 2018-05-11 00:01:36.124999 | 2018-05-11 00:01:36.124999 | Nothing |
-------------------------------------------------------------------------------------------------------
| 2 | Sam | false | 2018-05-11 00:01:36.124999 | 2018-05-11 00:01:36.124999 | NULL |
-------------------------------------------------------------------------------------------------------
我能够在编写原始SQL时获得所需的查询结果,但是我在尝试将其转换为活动记录查询时遇到了很多问题。这是否适合使用scenic gem?
以下是原始SQL查询:
SELECT u.*, (
SELECT notes AS yesterdays_notes
FROM reports AS r
WHERE r.created_at >= '2018-06-13 04:00:00'
AND r.created_at <= '2018-06-14 03:59:59.999999'
AND r.user_id = u.id
)
FROM users AS u
WHERE u.archived = FALSE
AND u.id NOT IN (
SELECT rr.user_id
FROM reports rr
WHERE rr.created_at >= '2018-06-14 04:00:00'
);
答案 0 :(得分:2)
我将如何做到这一点:
首先,选择昨天创建的最新报告的所有活动用户,并将其分配给var:
users = User.where(archived: false).joins(:reports)
.where.not('DATE(reports.created_at) IN (?)', [Date.today])
.where('DATE(reports.created_at) IN (?)', [Date.yesterday])
.select('users.id', 'users.name', 'notes')
现在,用户var将.select
中列出的attrs可用,因此您可以致电users.map(&:notes)
查看节点列表,包括nil
/ null
备注。< / p>
另一个可能派上用场的技巧是能够为.select
中列出的阁楼添加别名。例如,如果您想将users.id
存储为id
,则可以使用
...
.select('users.id as id', 'users.name', 'reports.notes')
你可以致电users.map(&:attributes)
看看这些最终结构是什么样的
可以找到有关可用Active Record查询的更多信息here
答案 1 :(得分:1)
users = User.joins(:reports).where("(reports.created_at < ? OR reports.created_at BETWEEN ? AND ?) AND (users.archived = ?)", Date.today.beginning_of_day, Date.yesterday.beginning_of_day, Date.yesterday.end_of_day, false).select("users.id, users.name, reports.notes").uniq
用户将返回#<ActiveRecord::Relation [....]
可能联接返回重复记录,因此请使用uniq
过滤报告
reports.created_at < Date.today.beginning_of_day OR yesterday.beginning_of_day > reports.created_at < Yesterday.end_of_day
需要报告为&#34;今天未完成报告,并显示昨天的报告说明(如果有)&#34;
users.archived = false
答案 2 :(得分:0)
我能够从这里发布的2个答案中得到所需的结果,但是,在做了一些更多的研究后,我认为使用scenic gem使用数据库视图是合适的方法,所以我将继续前进那个。
感谢您的投入!如果你想看看我的决定背后的一些推理,这个stackoverflow帖子很好地总结了它:https://stackoverflow.com/a/4378166/2909095
以下是我最终使用scenic gem的内容。我更改了实际的查询以更好地满足我的需求,但它解决了这个问题:
模型
# == Schema Information
#
# Table name: missing_reports
#
# id :bigint(8)
# name :string
# created_at :datetime
# updated_at :datetime
# previous_notes :text
# previous_notes_date :datetime
class MissingReport < ApplicationRecord
end
数据库视图
SELECT u.*, rs.notes AS previous_notes, rs.created_at AS previous_notes_date
FROM users AS u
LEFT JOIN (
SELECT r.*
FROM reports AS r
WHERE r.created_at < TIMESTAMP 'today'
ORDER BY created_at DESC
LIMIT 1
) rs ON rs.user_id = u.id
WHERE u.archived = FALSE
AND u.id NOT IN (
SELECT rr.user_id
FROM standups rr
WHERE rr.created_at >= TIMESTAMP 'today'
);
用法
def index
@missing_reports = MissingReport.all
end