Re: [Rails] Using :group with #count generating bad SQL in Postgres

81 views
Skip to first unread message

Carlos Figueiredo

unread,
Jul 23, 2013, 8:36:58 AM7/23/13
to rubyonra...@googlegroups.com

Your query is wrong...
You need group all columns you show that arent the result of an aggregate function...
So your group would be group('titles.*')

Em 22/07/2013 18:22, "yaw" <yawbo...@gmail.com> escreveu:
Rails 4.0.0, Ruby 2.0

class Title < ...
  ...

  has_many :comments

  def self.order_by_number_of_comments_descending
    select('titles.*, count(comments.id) AS comments_count').
    joins(:comments).
    group('titles.id').
    order('comment_count DESC')
  end

results in a malformed SQL on Postgres,


SELECT COUNT(*) AS count_all, titles.id AS titles_id FROM "titles"
INNER JOIN "comments" ON "comments"."title_id" = "titles"."id" GROUP BY titles.id ORDER BY comments_count DESC


I've contacted @steveklabnik and he'd re-open an issue reporting this bug. In the meantime, has anybody got around this? The SQL is all correct until you call group.
Thanks for helping

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/5def0eff-649b-4e00-9b87-154f02b9f34d%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Yaw Boakye elGran

unread,
Jul 23, 2013, 12:48:44 PM7/23/13
to rubyonra...@googlegroups.com
Can you write the right (no pun intended) query here? Thanks



For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
visit my blog @ yawboakye.blogspot.com     | call me on +233242057831 or +233273201210

Carlos Figueiredo

unread,
Jul 23, 2013, 3:11:16 PM7/23/13
to rubyonra...@googlegroups.com


def self.order_by_number_of_comments_descending
    select('titles.id, titles.name, titles.whatever, count(comments.id) AS comments_count').
    joins(:comments).
    group('titles.id, titles.name, titles.whatever').

    order('comment_count DESC')
  end

Assuming titles model is like (id, name, whatever)

The result query expected is:
SELECT COUNT(*) AS comments_count, titles.id AS titles_id, titles.name as titles_name, titles.whatever as titles_whatever FROM "titles"
INNER JOIN "comments" ON "comments"."title_id" = "titles"."id" GROUP BY titles.id, titles.name, titles.whatever ORDER BY comments_count DESC

Atenciosamente,

Carlos Figueiredo


Carlos Figueiredo

unread,
Jul 23, 2013, 3:18:02 PM7/23/13
to rubyonra...@googlegroups.com
Sorry...
Are there more columns on titles entity? If yes... the problem is that you tried to show columns you weren't grouping... and on postgresql it blows an exception... but if there is only one column on titles... (titles.id) so, I can't figure out what's the problem you mentioned...

What were your expected SQL to say that the result were malformed?

Atenciosamente,

Carlos Figueiredo

Yaw Boakye elGran

unread,
Jul 23, 2013, 8:28:12 PM7/23/13
to rubyonra...@googlegroups.com
There are at least 2 problems with how you recommend the query to be written:
  1. Why would titles.* work in regular SQL but not in Rails' select method? What would be the case if I have 100 columns on the titles table?
  2. During grouping, the normal SQL requirement is to group on a column that is on both tables. As far as I know, grouping can't be done on two tables when they don't a common column. In your group call, only titles.id would be useful. The rest won't

Did you try running the resulting query? It should throw an exception concerning the GROUP BY




For more options, visit https://groups.google.com/groups/opt_out.
 
 

Scott Ribe

unread,
Jul 23, 2013, 8:36:02 PM7/23/13
to rubyonra...@googlegroups.com
On Jul 23, 2013, at 6:28 PM, Yaw Boakye elGran <yawbo...@gmail.com> wrote:

> • During grouping, the normal SQL requirement is to group on a column that is on both tables. As far as I know, grouping can't be done on two tables when they don't a common column. In your group call, only titles.id would be useful. The rest won't

You seem to be confusing the grouping with the join condition. The join requires 1 (usually, sometimes more) column common to both tables. The grouping must include all columns not used in the aggregate function.


--
Scott Ribe
scott...@elevated-dev.com
http://www.elevated-dev.com/
(303) 722-0567 voice




Yaw Boakye elGran

unread,
Jul 24, 2013, 6:32:44 AM7/24/13
to rubyonra...@googlegroups.com
I think so, sorry for the misinformation. Thanks for the correction :)




--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.

Yaw Boakye elGran

unread,
Jul 24, 2013, 6:38:48 AM7/24/13
to rubyonra...@googlegroups.com
@Carlos this query still throws an exception:

def self.order_by_number_of_comments_descending
        select('titles.id,
titles.title, titles.submitter_name, titles.submitter_email, titles.created_at, titles.updated_at, count(comments.id) AS comments_count').
        joins(:comments).
        group('titles.id, titles.title, titles.submitter_name, titles.submitter_email, titles.created_at, titles.updated_at').
        order('comments_count DESC')
    end




still complaining about not finding comments_count :/

I'm using PostgreSQL 9.1.5

Yaw Boakye elGran

unread,
Jul 24, 2013, 6:40:27 AM7/24/13
to rubyonra...@googlegroups.com
Error message:

PG::Error: ERROR:  column "comments_count" does not exist
LINE 1: ...l, titles.created_at, titles.updated_at  ORDER BY comments_c...
                                                             ^
: SELECT COUNT(*) AS count_all, titles.id, titles.title, titles.submitter_name, titles.submitter_email, titles.created_at, titles.updated_at AS titles_id_titles_title_titles_submitter_name_titles_submitter_e FROM "titles" INNER JOIN "comments" ON "comments"."title_id" = "titles"."id" GROUP BY titles.id, titles.title, titles.submitter_name, titles.submitter_email, titles.created_at, titles.updated_at  ORDER BY comments_count DESC

Carlos Figueiredo

unread,
Jul 24, 2013, 7:10:46 AM7/24/13
to rubyonra...@googlegroups.com

Now I figured out what is the error...
I dont know why... But rails changed the column name where you count froum comments_count to count_all... And you refer it on your order by statement using the alias you choose...
I hope somone more experienced on rails help you fix it, but for now... U could do 2 fix...

You can call the alias rails choose (count_all) on your order statement (ugly way to solve)
Or you can call for count(*) without alias on your order statement (more practiced by dba... Less ugly to solve)

Carlos Figueiredo

unread,
Jul 24, 2013, 7:19:18 AM7/24/13
to rubyonra...@googlegroups.com

@Yaw, can you test if you change the way you call the count on postgres, rails still change the name of the column?

Ex. Try using count(comments.id) or count(1) besides count(*) on your query and let me know what happens...

Ps.: The ugly fix of my last email still works

Reply all
Reply to author
Forward
0 new messages