我的关系是Client
可以有很多ClientJobs
。我希望能够找到同时执行Job a
和Job b
的客户。我使用了3个选择框,因此我可以选择最多三个作业进行选择。选择框从数据库中填充。
我知道如何使用下面的查询测试1个作业。但我需要一种方法来使用AND
运算符来测试该客户端是否存在这两个作业。
@clients = Client.includes("client_jobs").where(
client_jobs: { job_name: params[:job1]})
不幸的是,按照下面的操作很容易进行IN
操作,但我认为AND
的语法应该类似......我希望
@lients = Client.includes("client_jobs").where(
client_jobs: { job_name: [params[:job1], params[:job2]]})
编辑:从下面的答案中发布命中数据库的sql语句
Core Load (0.6ms) SELECT `clients`.* FROM `clients`
CoreStatistic Load (1.9ms) SELECT `client_jobs`.* FROM `client_jobs`
WHERE `client_jobs `.`client_id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,........)
第二个查询遍历数据库中的每个client_job。它从未针对params[:job1], params[:job2]
等进行测试。因此@clients
会导致nil
崩溃我的视图模板
(undefined method `map' for nil:NilClass
答案 0 :(得分:3)
在我看来,自我加入的更好方法是简单地加入ClientJobs
,然后使用GROUP BY
和HAVING
子句过滤掉那些与给定关联完全匹配的记录记录。
performed_jobs = %w(job job2 job3)
Client.joins(:client_jobs).
where(client_jobs: { job_name: performed_jobs }).
group("clients.id").
having("count(*) = #{performed_jobs.count}")
让我们来看看这个问题:
ClientJob
加入Client
并过滤掉那些定义的三个作业中的任何一个(它使用IN子句)< / LI>
group
我们Client.id
这些已加入的记录,以便我们让客户回来having
子句确保我们只返回那些加入了3 ClientJob
条记录的客户端,即只有那些定义了所有三个客户端作业的客户。 HAVING(COUNT(*) = ...)
的诀窍是将IN
子句(实际上是OR
- 选项列表)转换为&#34;必须拥有所有这些&#34 ;子句。