gpt4 book ai didi

sql - 复杂的 Rails 查询 - 联合?子选择?我还能使用 named_scope 吗?

转载 作者:可可西里 更新时间:2023-11-01 06:48:23 27 4
gpt4 key购买 nike

我喜欢 Rails 的部分原因是我讨厌 SQL - 我认为它更像是一种汇编语言,应该使用更高级别的工具(如 ActiveRecord)进行操作。然而,我似乎已经达到了这种方法的极限,而且我对 SQL 的理解超出了我的理解范围。

我有一个包含很多子记录的复杂模型。我还有一组 30-40 个 named_scopes 来实现来自客户端的业务逻辑。这些作用域有条件地链接在一起,这就是为什么我有那些 joins_ 作用域,这样连接就不会被破坏。

我有几个不能正常工作,或者至少不是客户希望他们工作的方式。这是模型结构的一个粗略概念,其中包含一些命名范围(示例中并非全部需要),它们说明了我的方法并指出了我的问题。 (请原谅任何语法错误)

class Man < ActiveRecord::Base
has_many :wives

named_scope :has_wife_named lambda { |n| { :conditions => { :wives => {:name => n}}}}
named_scope :has_young_wife_named lambda { |n| { :conditions => { :wives => {:name => n, :age => 0..30}}}}
named_scope :has_yw_named_v2 lambda { |n| { :conditions => ["wives.name = ? AND wives.age <= 30", n]}}
named_scope :joins_wives :joins => :wives

named_scope :has_red_cat :conditions => { :cats => {:color => 'red'}}
named_scope :has_cat_of_color lambda { |c| { :conditions => { :cats => {:color => c}}}}
named_scope :has_7yo_cat :conditions => { :cats => {:age => 7}}
named_scope :has_cat_of_age lambda { |a| { :conditions => { :cats => {:age => a}}}}
named_scope :has_cat_older_than lambda { |a| { :conditions => ["cats.age > ?", a] }}
named_scope :has_cat_younger_than lambda { |a| { :conditions => ["cats.age < ?", a] }}
named_scope :has_cat_fatter_than lambda { |w| { :conditions => ["cats.weight > ?", w] } }
named_scope :joins_wives_cats :joins => {:wives => :cats}
end

class Wife < ActiveRecord::Base
belongs_to :man
has_many :cats
end

class Cat < ActiveRecord::Base
belongs_to :wife
end
  1. 我可以找到妻子有七岁猫的男人

    @men = Man.has_red_cat.has_7yo_cat.joins_wives_cats.scoped({:select => 'DISTINCT men'})

    而且我什至可以找到妻子养猫超过 20 磅和超过 6 岁的男人

    @men = Man.has_cat_fatter_than(20).has_cat_older_than(5).joins_wives_cats.scoped({:select => 'DISTINCT men'})

    但这不是我想要的。我想找到那些妻子中至少有一只红猫和一只七岁猫的男人,它们不一定是同一只猫,或者找到那些妻子中至少有一只猫超过给定体重且一只比给定年龄大的猫。
    (在后续示例中,请假设存在适当的 joins_DISTINCT)

  2. 我可以找到娶了名叫以斯帖的男人

    @men = Man.has_wife_named('Esther')

    我什至可以找到妻子名叫 Esther、Ruth 或 Ada 的男人(太棒了!)

    @men = Man.has_wife_named(['Esther', 'Ruth', 'Ada'])

    但我想找到妻子名叫 Esther AND Ruth AND Ada 的男人。

  3. 呵呵,开个玩笑,其实,我需要这个:我可以找到娶不到30岁老婆的男人,名字叫Esther

    @men = Man.has_young_wife_named('Esther')

    寻找娶了以斯帖、露丝或艾达为妻的男人

    @men = Man.has_young_wife_named(['Esther', 'Ruth', 'Ada'])

    但如上所述,我想找到有名叫 Esther AND Ruth AND Ada 的年轻妻子的男人。幸运的是,在这种情况下,最低年龄是固定的,但最好也指定最低年龄。

  4. 有没有一种方法可以使用散列语法来测试不等式,或者您是否总是必须恢复为 :conditions => ["", n] - 注意两者之间的区别has_young_wife_namedhas_yw_named_v2 - 我更喜欢第一个,但该范围仅适用于有限值。如果您正在寻找一位老妻子,我想您可以使用 a..100 但是当一位妻子年满 101 岁时,她就会放弃搜索。 (嗯。她会做饭吗?j/k)

  5. 有没有办法在范围内使用范围?如果 :has_red_cat 可以以某种方式使用 :has_cat_of_color,或者如果有某种方法可以使用其父记录中的子记录的范围,我会喜欢它,所以我可以把将与猫相关的作用域放入 Wife 模型中。

我真的不想在不使用 named_scope 的情况下直接在 SQL 中执行此操作,除非有其他更好的东西 - 对插件的建议和不受欢迎的东西,或者对我的 SQL 类型的指导需要学习。一位 friend 建议 UNION 或子搜索可以在这里工作,但在 Rails 的上下文中似乎没有太多讨论。我对 View 一无所知——它们有用吗?是否有适合 rails 的方法来制作它们?

谢谢!

因为我要去圣艾夫斯
我遇到了一个有七个老婆的男人
每个妻子都有七个麻袋
每个袋子里有七只猫
每只猫有七个工具包
工具包、猫、麻袋、妻子
有多少人要去圣艾夫斯?

最佳答案

好吧,我用像这样的 named_scope 取得了很好的结果:

named_scope :has_cat_older_than   lambda { |a| { :conditions => ["men.id in ( select man_id from wives where wives.id in ( select wife_id from cats where age > ? ) )", a] } }

named_scope :has_young_wife_named lambda { |n| { :conditions => ["men.id in ( select man_id from wives where name = ? and age < 30)", n] } }

我现在可以成功了

Member.has_cat_older_than(6).has_young_wife_named('Miriam').has_young_wife_named('Vashti')

并得到我所期待的。这些作用域不需要使用联接,而且它们似乎可以很好地与其他样式的联接配合使用。

w00t!

关于这是否是执行此操作的有效方法,或者是否有更“rails-y”的方法的评论。将来自另一个模型的范围作为 sql 子查询片段包含在内的某些方法可能很有用...

关于sql - 复杂的 Rails 查询 - 联合?子选择?我还能使用 named_scope 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1021018/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com