Rails 3: Difference between Relation.count and Relation.all.count -
moin,
i stumbled upon inconsistency in activerecord.
tried used combinations of values in 2 columns of large table. first idea:
select distinct col1, col2 table
imagine rails app organizes meals model , each meal has_many :noodles
each noodle has attributes (and hence db table columns) color
, shape
. goal number of present combinations of color
, shape
single meal.
since ar not provide "distinct" method used
my_meal.noodles.select("distinct color, shape")
and got (in rails console stdout) 6 line output of 8 noodle objects (respectively string representations). but:
>> my_meal.noodles.select("distinct color, shape").count => 1606
in fact my_meal
contains 1606 noodles. if convert the relation array , size of or use .all.count
result correct.
so question is, why ar output 8 objects count db lines?
a similar problem seems mentioned here no answer given.
thanks , best regards, tim
okay, tadman pushing me in right direction.
i digged deeper (especially in log files) , found little bit weird.
the problem caused number of selected columns. if 1 selects 1 column , counts result
my_meal.noodles.select("distinct color").count
activerecord creates following sql statement:
select count(distinct color) count_id "noodles" ("noodles".meal_id = 295)
in case 1 selects 2 or more columns , applies count
it
my_meal.noodles.select("distinct color, shape").count
activerecord forgets select clause , creates:
select count(*) count_id "noodles" ("noodles".meal_id = 295)
this may right, since (sql's) count
allows 1 or less columns parameters. add group
before count
, fine:
my_meal.noodles.select("distinct color, shape").group("color, shape").count select count(*) count_all, color, shape color_shape "noodles" ("noodles".meal_id = 295) group color, shape
apart as color_shape
exact expected. but... returns this:
>> my_meal.noodles.select("distinct color, shape").group("color, shape").count => {star=>309, circle=>111, spaghetti=>189, square=>194, triangle=>179, bowtie=>301, shell=>93, letter=>230} >> my_meal.noodles.select("distinct color, shape").group("color, shape").count.class => activesupport::orderedhash
this weird return value (apart order depends on db) identical result , return value of
my_meal.noodles.group("shape").count
conclusion:
pointed out here there still gap between relations (may mathematical or arel relations) , activerecord::relations.
can see advantages of pressing result in patterns of model possible (at least in context of rails app).
real relations not result of combination of several operations result of concatenation of operations. in general chainability of activerecord::relations great thing there design decisions cannot follow.
if can't depend on assurance each action returns new relation work with, looses of inuitional appeal.
as solution of problem, use above-mentioned group
solution , kind of dirty workaround count operation:
my_meal.noodles.select("distinct color, shape").group("color, shape").all.count
this compresses results acceptable minimum before pulling them out of database , creating expensive objects count them. alternatively 1 use handwritten sql query, why have rails , not use it, huh? ;-)
thanks help,
tim
Comments
Post a Comment