2012-12-24 18 views
2

我無法弄清楚如何正確計數作用域中的對象。Ruby/Rails使用MySQL中的計算列對作用域中的對象進行計數

在這個例子中,我們假設產品(「skus」)有lat和lng,用戶也是如此。

我有一個可行的的find_by_sql例如:

def self.with_max_distance(user, distance) 
    Sku.find_by_sql(
    <<-eos 
     SELECT *, 
     (3959 * acos(cos(radians(#{user.lat})) * cos(radians(skus.lat)) 
     * cos(radians(skus.lng) - radians(#{user.lng})) + sin(radians(#{user.lat})) 
     * sin(radians(skus.lat)))) AS distance 
     FROM skus 
     HAVING distance < #{distance} 
    eos 
    ) 
    end 

我能夠得到以下的範圍,以部分工作:

scope :scope_with_max_distance, lambda { |user, distance| 
    { :select => "skus.*, (3959 * acos(cos(radians(#{user.lat})) * cos(radians(skus.lat)) * cos(radians(skus.lng) - radians(#{user.lng})) + sin(radians(#{user.lat})) * sin(radians(skus.lat)))) AS distance", 
     :having => "distance < #{distance}" 
    } 
    } 

範圍似乎正確地獲取的對象,雖然我沒有廣泛測試,如果我將其與其他示波器連接起來,它似乎工作。

但是,我無法count()的對象,這真的很煩人。我知道我可以使用length(),但事實上,它不與計數工作,讓我想知道是否有更好的方法來做到這一點。

1.9.3p125 :048 > Sku.scope_with_max_distance(User.first, 50).limit(10).count 
    User Load (0.5ms) SELECT `users`.* FROM `users` LIMIT 1 
    (0.6ms) SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM `skus` HAVING distance < 50 LIMIT 10) subquery_for_count 
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'distance' in 'having clause': SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM `skus` HAVING distance < 50 LIMIT 10) subquery_for_count 

我真的很感激任何建議或想法 - 我已經嘗試了很多不同的方法,但一直沒能找到一個完全可行的方法。請讓我知道,如果這個問題需要更多的澄清。

回答

4

count將取代你的select只需要簡單的元素,以儘可能有效地建立一個計數。它不會檢查其他約束來確保SQL有效。您可以將having中的distance別名替換爲您將選擇解決此問題的公式。另外,我建議您更換havingwhere避免隱含的分組不是數據庫移植:

scope :scope_with_max_distance, lambda { |user, distance| 
    distance_formula = "(3959 * acos(cos(radians(#{user.lat})) * cos(radians(skus.lat)) * cos(radians(skus.lng) - radians(#{user.lng})) + sin(radians(#{user.lat})) * sin(radians(skus.lat))))" 
    { :select => "skus.*, #{distance_formula} AS distance", 
    :where => "#{distance_formula} < #{distance}" 
    } 
} 

最後一件事,你在呼喚limit(10)count這將意味着數絕不會超過10。這是更大本質上不是錯誤的,但我不確定這是你的意思。

+0

總體感覺 - 我應該想到這一點> _ <。謝謝! – Justin