如何编写Rails查询找出CheckIn与关联Program的client_id不匹配记录
问题
我有一个CheckIn模型,它同时关联Client和Program模型,包含client_id和program_id字段;Program模型同样关联Client模型。现在需要找出所有关联的Program所属Client与自身所属Client不一致的CheckIn记录,并统计这种不匹配情况的出现频率。
模型定义如下:
class CheckIn < ApplicationRecord belongs_to :program belongs_to :client end class Program < ApplicationRecord belongs_to :client end class Client < ApplicationRecord has_many :check_ins has_many :programs end
以下是一条不匹配的记录示例:
#<CheckIn:0x00000001149ef9e8> { :id => 336964, :created_at => Wed, 29 Jun 2022 17:06:19.567000000 EDT -04:00, :updated_at => Wed, 29 Jun 2022 17:06:30.280633000 EDT -04:00, :client_id => 45290, :program_id => 26266, } #<Program:0x00000001141e4d70 id: 26266, client_id: 46220, # 与CheckIn的client_id(45290)不匹配 created_at: Tue, 18 Oct 2022 07:19:13.735740000 EDT -04:00, updated_at: Tue, 18 Oct 2022 07:19:13.735740000 EDT -04:00 >
我尝试了下面的代码,但不知道如何引用CheckIn自身的client_id:
CheckIn.joins(:program).where.not(programs: {client_id: CLIENT_ID_HERE})
解决方案
1. 查询所有不匹配的CheckIn记录
你可以直接在查询条件中对比两个表的client_id字段,有两种写法可选:
写法一:直接使用SQL字符串条件
# 获取所有client_id不匹配的CheckIn记录 mismatched_check_ins = CheckIn.joins(:program).where.not('check_ins.client_id = programs.client_id')
写法二:使用Arel语法(更安全,避免硬写SQL)
# 通过Arel引用表字段,避免字符串拼接风险 check_ins_table = CheckIn.arel_table programs_table = Program.arel_table mismatched_check_ins = CheckIn.joins(:program).where( check_ins_table[:client_id].not_eq(programs_table[:client_id]) )
2. 统计不匹配频率
要统计不匹配记录的数量或占比,直接基于上面的查询结果调用统计方法:
# 统计不匹配记录总数 mismatch_count = mismatched_check_ins.count # 计算不匹配占比(保留两位小数) total_check_ins = CheckIn.count mismatch_ratio = (mismatch_count.to_f / total_check_ins) * 100 puts "不匹配占比:#{sprintf("%.2f", mismatch_ratio)}%"
关键说明
joins(:program)会将CheckIn表与Program表做内连接,只保留存在对应Program的CheckIn记录- 两种查询写法都能精准筛选出
CheckIn.client_id与Program.client_id不相等的记录,满足你的需求
内容的提问来源于stack exchange,提问作者Jeremy Thomas
相关产品推荐
相关产品推荐

