I have this query:
SET @current_group = NULL;
SET @current_count = 0;
SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c
FROM notifies
G ROUP BY user_id, c
ORDER BY id desc LIMIT 0 , 10
If i launch it it works
but if i put it in a find_by_sql method like:
Notify.find_by_sql("SET @current_group = NULL; SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c FROM notifies GROUP BY user_id, c ORDER BY id desc LIMIT 0 , 10")
It returns this error:
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WH' at line 1:
How can i do?
thanks
It's because find_by_sql
only works with a single statement.
Setting variables happen in separate statements. set
specifically is in the Database Administration section, number 12.4.4, and select
is in Data Manipulation section, number 12.2.7. Consoles (usually) allow multiple statements, and keep the variables around, but ActiveRecord queries do not.
To allow multiple statements, I think you have to maintain a persistent connection with the database, which Rails doesn't do (edit: normally). But I'm not certain about that - if anyone else knows, I'd love a more definite reason.
Edit: actually, I have a solution for you. Try this:
items = YourModel.transaction do
YourModel.connection.execute("SET @current_group = NULL;")
YourModel.connection.execute("SET @current_count = 0;")
# this is returned, because it's the last line in the block
YourModel.find_by_sql(%Q|
SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c
FROM notifies
GROUP BY user_id, c
ORDER BY id desc LIMIT 0 , 10
|)
end
All those run in a single transaction, and any variables / settings inside the transaction block will persist between queries. You're still bound to a single statement per query though. There might be a way to do it without an actual transaction wrapping the whole set, but I haven't looked for it - most likely you want one, or you now have a very specific thing to look for if you know you don't.
Enjoy!