Reputation: 973
I would like to identify and count the posts that have a specific number of messages and a post.location that is not nil.
I have approximately 100k rows and it is for a statistical use so I need fast queries (I might have to index post.location by the way).
How can I do it the easiest and quickest way?
Here is my schema :
create_table "posts", :force => true do |t|
t.string "ref"
t.string "title"
t.string "author"
t.datetime "created_at"
t.datetime "updated_at"
t.string "location"
t.float "lat"
t.float "long"
end
create_table "messages", :force => true do |t|
t.integer "post_id"
t.integer "status_id"
t.integer "user_id"
t.string "content"
t.datetime "created_at"
t.datetime "updated_at"
t.float "lat"
t.float "long"
end
add_index "messages", ["post_id"], :name => "index_messages_on_post_id"
add_index "messages", ["created_at"], :name => "index_messages_on_created_at"
Upvotes: 2
Views: 99
Reputation: 23648
The SQL Query you are looking for should look a lot like this:
SELECT COUNT(posts.id)
FROM posts
JOIN messages ON (posts.id = messages.post_id)
GROUP BY (posts.id) HAVING (count(messages.id) > ?)
WHERE posts.location IS NOT NULL
You can then convert that to a ActiveRecord Query or just use find_by_sql
.
(I wrote this from memory so you might have to tweak it in some places .. but the general idea should work).
Upvotes: 3
Reputation: 973
OK I managed to get through it thanks to both Tigraine's and az7ar's answers. Here's what worked out:
Post.joins(:messages).select('post_id as id').group("post_id").having("count(*) = 1").where('location IS NOT NULL')
Thank you Tigraine for the JOIN advice and az7ar for the .where("location IS NOT NULL")
syntax.
Upvotes: 0
Reputation: 5237
You can use this scope in you Post model
scope :give_a_valid_name, lambda {|n| joins(:messages).having("COUNT(messages.id) = #{n}").where("location IS NOT NULL")}
Then use Post.give_a_valid_name(5).size to get the number of posts that have 5 messages.
Hope this helps.
Upvotes: 1