4

私は次のモデルを持っています

class Courier < ActiveRecord::Base
  has_many :coverages
end

class Coverage < ActiveRecord::Base
  belongs_to :courier
  belongs_to :country_code
end

class CountryCode < ActiveRecord::Base      
end

そして、私は次のクエリを持っています:

# could i translate this into cleaner arel?
result = Courier.find_by_sql(<<SQL
          select * from
          (
            select cc.*, cv.rate from couriers cc, coverages cv
            where cv.country_code_id=#{country.id} and cv.courier_id=cc.id
          union
            select cc.*, cv.rate from couriers cc, coverages cv
            where cv.country_code_id is null
              and cv.courier_id=cc.id
              and cv.courier_id not in (select courier_id from coverages where country_code_id=#{country.id})
          ) as foo order by rate asc
SQL
)

つまり、特定の国コードをカバーするか、代わりに空の国コードをカバーするすべての宅配便業者を探しています(フォールバック)。

クエリは機能しますが、それを書くためのより良い方法があるかどうか疑問に思っていますか?

4

2 に答える 2

1

arelを使用すると、似たようなものを入手するのはそれほど難しくないようです。

country_code = ...
c=Courier.arel_table
cv=Coverage.arel_table    
courier_ids_with_country_code= Coverage.select(:courier_id).where(:country_code=>country_code)
coverage_ids_and_condition= Coverage.select(:id)
                                    .where(cv[:country_code]
                                               .eq(nil)
                                               .and(cv[:courier_id]
                                                          .in(courier_ids_with_country_code)))
coverage_ids_with_country_code= Coverage.select(:id)
                                        .where(:country_code=>country_code)

coverage_union_joined_with_couriers = Coverage.include(:courier)
                                              .where(cv[:id]
                                                     .in(coverage_ids_with_country_code
                                                         .union(coverage_ids_and_condition)))

これにより、指定された条件のカバレッジと関連する宅配便を取得する1つのクエリが実行されます。意図した結果を得るためにこれを適応させることは非常に難しいとは思いません。

于 2013-02-08T15:38:12.787 に答える
1

を保持したい場合はfind_by_sql、クエリを次のように要約できます。

result = Courier.find_by_sql [
  "SELECT cc.*, cv.rate
  FROM couriers cc inner join coverages cv on cv.courier_id = cc.id
  WHERE cv.country_code_id = ?
    OR (cv.country_code_id is null AND cv.courier_id NOT IN (SELECT courier_id FROM coverages WHERE country_code_id= ? ))
  ORDER BY cv.rate asc", country.id, country.id ]
于 2011-12-30T09:50:51.953 に答える