比较具有特定值的表的两列;如果匹配,则返回另一个

时间:2016-06-04 00:37:28

标签: ruby-on-rails ruby-on-rails-4 activerecord

我的应用程序中有以下模型,它以多种方式与另一个模型相关

class XYZRelated < ActiveRecord::Base
    belongs_to :xyz1, class_name: 'XYZ', foreign_key: 'xyz1_id'
    belongs_to :xyz2, class_name: 'XYZ', foreign_key: 'xyz2_id'
end

此外,我已经进行了验证,确保xyz1_id != xyz2_id,并且即使ID已被交换,两个ID [xyz1_id, xyz2_id]的每个组合都是唯一的,即有一行[3,1] }表示[1,3]不允许其他行。

对于JSON API,我希望能够在相关模型中搜索一个XYZ_ID,并尽可能高效地返回另一个ID。

但是,我不知道我要搜索的ID是存储在xyz1_id还是xyz2_id中。因此,我希望将任意ID与xyz1_id和xyz2_id进行比较,如果它匹配一列,我将返回另一个(除非另一个为NULL,在这种情况下我不会返回匹配)。

目前我正在这样做:

def find_all_ids(xyz_id)
    l = XYZRelated.where(xyz1_id: xyz_id).where.not(xyz2_id: nil)
                  .pluck(:xyz2_id).to_a
    l.concat XYZRelated.where(xyz2_id: xyz_id).where.not(xyz1_id: nil)
                       .pluck(:xyz1_id).to_a
    return l
end

我认为有更好的方法可以做到这一点,或者甚至是更好的布局数据库的方法,以避免这个问题。但是,我对高级SQL查询不太熟悉,在Rails文档中找不到任何内容。

我怎样才能更有效地做到这一点,以避免两个单独的查询和结果的连接?谢谢!

1 个答案:

答案 0 :(得分:1)

这是两个单独的查询,您可以使用UNION来组合它们,但我不太确定触发单个查询与之间的性能差异 UNION

以下内容使其显着简化

XYZRelated.where("xyz1_id = :xyz_id OR xyz2_id = :xyz_id", xyz_id: xyz_id)
          .pluck(:xyz1_id, :xyz2_id).uniq.compact - [xyz_id]

说明 -

  
      
  1. 查询xyz1_id或xyz2_id设置为xyz_id的所有记录
  2.   
  3. 将阵列展平(2d阵列为1d阵列)
  4.   
  5. 删除重复项(大约一半的数组是xyz_id,因为每个匹配的记录至少有一个id = xyz_id)
  6.   
  7. 删除NULL条目(这样您就不必关心“其他”id为NULL)
  8.   
  9. 然后删除输入参数 xyz_id ,因为它显然会在数组中
  10.