Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql Rails 5使用includes()和where()左外连接_Mysql_Ruby On Rails_Activerecord_Left Join_Ruby On Rails 5 - Fatal编程技术网

Mysql Rails 5使用includes()和where()左外连接

Mysql Rails 5使用includes()和where()左外连接,mysql,ruby-on-rails,activerecord,left-join,ruby-on-rails-5,Mysql,Ruby On Rails,Activerecord,Left Join,Ruby On Rails 5,我在使用includes()和where()获取预期行为方面花了很长时间 我想要的结果: -所有学生(即使他们没有登记入住) -所有在图书馆登记的人 我得到的结果是: -只有在图书馆登记的学生 -所有在图书馆登记的学生 目前我的代码基于以下内容: 它描述了我想要的行为: SELECT first_name, C.id FROM students S LEFT OUTER JOIN check_ins C ON C.student_id = S.id AND location IN ('Libr

我在使用includes()和where()获取预期行为方面花了很长时间

我想要的结果:
-所有学生(即使他们没有登记入住)
-所有在图书馆登记的人

我得到的结果是:
-只有在图书馆登记的学生
-所有在图书馆登记的学生


目前我的代码基于以下内容:

它描述了我想要的行为:

SELECT first_name, C.id FROM students S LEFT OUTER JOIN check_ins C ON C.student_id = S.id AND location IN ('Library');
如果在这个包含查询的情况下,没有任何注释 物品,所有物品仍将被加载

我的代码:

此SQL查询提供了我想要的连接行为:

SELECT first_name, C.id FROM students S LEFT OUTER JOIN check_ins C ON C.student_id = S.id AND location IN ('Library');

我认为这是创建所需查询的唯一方法

Student.joins("LEFT OUTER JOIN check_ins ON check_ins.student_id = students.id AND check_ins.location = 'Library'")

参考资料:

就纯SQL而言,您想要的是:

LEFT OUTER JOIN "check_ins" ON "check_ins"."student_id" = "students"."id"
  AND location IN ('Library')
但是(afaik)无法让ActiveRecord将关联标记为已加载

老实说,我从来不喜欢只预加载关联的一个子集 因为应用程序的某些部分可能假定它是 满载的。只有当您将数据传送到 显示它。
-罗伯特·潘科维茨基

<> P>所以在这种情况下,你应该考虑预加载所有的数据,并使用类似A的东西来选择<代码> CyjysIs<代码> > < /P>
我还建议您为位置创建一个单独的表。

尝试了一种使用具有关系的作用域的新方法,期望预加载所有内容并将其过滤掉,但令人惊喜的是,作用域实际上为我提供了我想要的准确行为(直接到急切加载)

结果如下:

此ActiveRecord调用会拉入完整的学生列表,并加载签入:

@students = Student.all.includes(:check_ins)
签入的范围可以限制在has\u many声明中:

Class Student < ApplicationRecord
    has_many :check_ins, -> {where('location = 'Library'}, dependent: :destroy
end

宾果

p、 您可以在此处阅读有关将作用域与关联一起使用的更多信息:

子查询将类似于学生的
(选择count('check\u-ins.location'),其中的'check\u-ins.location')。check\u-IN\u-count
。我已经好几年没有接触过MySQL了,也没有安装它来试用。你就是那个人,一个多小时后,我发现你的加入代码解决了我的一个大问题!我的目标是急切地加载关联以最小化查询的数量。虽然这种方法可以获得正确的数据,但它使用了大量的查询来获得这些数据。
{where('location='Library'}
=>
{where('location='Library')}
{where(location:'Library')}
Student.joins("LEFT OUTER JOIN check_ins ON check_ins.student_id = students.id AND check_ins.location = 'Library'")
LEFT OUTER JOIN "check_ins" ON "check_ins"."student_id" = "students"."id"
  AND location IN ('Library')
class Student < ApplicationRecord
  has_many :check_ins

  def self.joins_check_ins
    joins( <<~SQL
      LEFT OUTER JOIN "check_ins" ON "check_ins"."student_id" = "students"."id"
      AND location IN ('Library')
    SQL
    )
  end
end
irb(main):041:0> Student.joins_check_ins.map {|s| s.check_ins.loaded? }
  Student Load (1.0ms)  SELECT "students".* FROM "students" LEFT OUTER JOIN "check_ins" ON "check_ins"."student_id" = "students"."id"
AND location IN ('Library')
=> [false, false, false]

irb(main):042:0> Student.joins_check_ins.map {|s| s.check_ins.size }
  Student Load (2.3ms)  SELECT "students".* FROM "students" LEFT OUTER JOIN "check_ins" ON "check_ins"."student_id" = "students"."id"
AND location IN ('Library')
   (1.2ms)  SELECT COUNT(*) FROM "check_ins" WHERE "check_ins"."student_id" = $1  [["student_id", 1]]
   (0.7ms)  SELECT COUNT(*) FROM "check_ins" WHERE "check_ins"."student_id" = $1  [["student_id", 2]]
   (0.6ms)  SELECT COUNT(*) FROM "check_ins" WHERE "check_ins"."student_id" = $1  [["student_id", 3]]
@students = Student.all.includes(:check_ins)
Class Student < ApplicationRecord
    has_many :check_ins, -> {where('location = 'Library'}, dependent: :destroy
end
  Student Load (0.7ms)  SELECT "students".* FROM "students"
  CheckIn Load (1.2ms)  SELECT "check_ins".* FROM "check_ins" WHERE location = 'Library') AND "check_ins"."student_id" IN (6, 7, 5, 3, 1, 8, 9, 4, 2)