2012-09-05 9 views
11

mogę użyć następujących:Jak mogę policzyć wynik kwerendy .Rrupy ActiveRecord? Łańcuchowym .count zwraca hash

User.where("zip_code = '48104'").group('users.id').count 

dostać skrótów, takich jak:

{195=>1, 106=>1, 120=>1, 227=>1, 247=>1, 264=>1, 410=>1} 

Czy istnieje sposób mogę policzyć tych skrótów i po prostu wrócić , zamiast powyższego wyniku?

Wiem, że to nie ma sensu w powyższym scenariuszu i mogę to zrobić, nie używając klauzuli grupy. Ale pracuję nad bardziej złożonym zapytaniem, w którym muszę to zaimplementować. Z góry dziękuję.

+2

Możesz uzyskać długość * dowolnego * hasza z '.length' – meagar

+1

@meagar: To jednak wymaga zwrócenia wszystkich rekordów jako obiektów, a następnie ich zliczenia. To trochę świnia wydajności. –

Odpowiedz

19

Spróbuj:

User.where("zip_code = '48104'").group('users.id').count.length 
+0

w jaki sposób można to zrobić bez wyciągania wszystkich rekordów z bazy danych? – orourkedd

+0

Możesz to zrobić z podselekcją w surowym SQL. Będziesz musiał użyć surowego połączenia z bazą danych, aby to zrobić: http://apidock.com/rails/ActiveRecord/Base/connection – robbrit

+0

To hackish, ale innym sposobem na zmniejszenie kwoty pobranej z bazy danych jest wrzucenie zakres aselect ("id"), aby uniknąć przywoływania innych kolumn. –

3

Jeśli chcesz dodać Wartości mieszań razem następnie:

{key1: 1, key2: 2}.values.inject(:+) # => 3 

Jeśli chcesz po prostu liczbę klawiszy następnie:

{key1: 1, key2: 2}.length # => 2 
+0

+1 Działa! Dzięki. – Myxtic

8

Przyjęty odpowiedź nie jest skalowalne. Zastosowanie metody @ robbrit w zapytaniu z 25 000 pasujących użytkowników spowoduje pobranie 25 000 wyników (tj. Tablicy zawierającej 25 000 elementów) do pamięci, a następnie zliczenie tablicy elementów. Oto metoda, która zrobi to bez wyciągania wszystkie dane:

def count_query(query) 
    query = "SELECT count(*) AS count_all FROM (#{query.to_sql}) x" 
    ActiveRecord::Base.connection.execute(query).first.try(:[], 0).to_i 
end 

Jest on stosowany tak:

query = User.where("zip_code = '48104'").group('users.id') 
count = count_query(query) 

Działa to dla mnie MySQL, btw.

To była inspirowana przez tego faceta: https://github.com/mrbrdo/active_record_group_count/blob/master/lib/active_record_group_count/scope.rb

0

inny sposób, przydatna, gdy wartości mogą być> 1.

User.where("zip_code = '48104'").group('users.id').count.values.sum 
2

Jak powiedział wcześniej przez orourkedd przyjętą odpowiedź nie jest wielki, kiedy do czynienia z dużą ilością rekordów. Niedawno napotkałem ten problem i mam duże tabele, które zdecydowanie nie chcę załadować do pamięci. Oto, co działa dla mnie.

users=User.where("zip_code = '48104'").group('users.id') 
user_count=User.where(id: users.select(:id)).count 

Szyny będą obsługiwać użytkowników.wybierz część jak podzapytanie. Działa to z Rails 4

Powiązane problemy