avram icon indicating copy to clipboard operation
avram copied to clipboard

Add new `having` methods

Open jwoertink opened this issue 3 years ago • 0 comments

I think using HAVING isn't super common, but when you need it, it's pretty nice.

I had a thought about how this might look, but since I rarely use this function, I'm not sure if my idea here covers a wide enough case or not.. I think to start we could have 2 methods. The first being having which might work similar to where(raw_sql : String). This would let you just write what you need as an escape hatch.

The second (and subsequent) methods would work similar to a column method, but also piggy back off the aggregate functions.

# or maybe just having_count ?
def having_select_count(exact_match : Int)
  having_select_count.eq(exact_match)
end

def having_select_count
end

Then it could look like this:

# give me all users that have exactly 4 draft posts
UserQuery.new.where_posts(PostQuery.new.published(false).having_select_count(4)).group(&.id)

# give me all users that have at least 2 published posts
UserQuery.new.where_posts(PostQuery.new.published(true).having_count.gte(2)).group(&.id)

This would give us

SELECT users.*
FROM users
INNER JOIN posts on posts.user_id = users.id
WHERE posts.published = 'f'
GROUP BY users.id
HAVING COUNT(posts.*) = 4

SELECT users.*
FROM users
INNER JOIN posts on posts.user_id = users.id
WHERE posts.published = 't'
GROUP BY users.id
HAVING COUNT(posts.*) >= 2

Or of course you could do UserQuery.new.where_posts(...).group(&.id).having("COUNT(posts.*) > ?", 4)

The others could be like having_sum having_min, having_max, etc...

jwoertink avatar Aug 12 '22 21:08 jwoertink