

Rails 7 adds the ability to delete and update queries using GROUP_BY and HAVING
source link: https://blog.saeloun.com/2021/12/15/rails-7-updates-to-group-by-and-having
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

For a very long time in Rails, it was not possible to combine delete statements with GROUP_BY and HAVING queries. It does seem like something that should have been supported out of the box, but unfortunately was overlooked — until now!
Before
Using GROUP_BY or HAVING in a delete statement was ignored. Let’s look at an example.
Here, a user has multiple votes, and we’re trying to count users who have less than three votes.
User.joins(:votes).group("users.id").having("count(votes.id) < 3").count
=> {2=>1, 1=>2}
If we do update_all
with group
and having
clause ActiveRecord would ignore it.
User.joins(:votes).group("users.id").having("count(votes.id) < 3").update_all(consistent: true)
# actual
UPDATE "users" SET "consistent" = ? WHERE "users"."id" IN (
SELECT "users"."id" FROM "users" INNER JOIN "votes" ON "votes"."user_id" = "users"."id"
) [["consistent", "t"]]
# expected
UPDATE "users" SET "consistent" = ? WHERE "users"."id" IN (
SELECT "users"."id" FROM "users" INNER JOIN "votes" ON "votes"."user_id" = "users"."id"
GROUP BY users.id HAVING (count(votes.id) < 3)
) [["consistent", "t"]]
However, when we try to delete these users, we end up with an error.
User.joins(:votes).group("users.id").having("count(votes.id) < 3").delete_all
=> Traceback (most recent call last):
1: from (irb):10
ActiveRecord::ActiveRecordError (delete_all doesn't support group, having)
After
Fortunately, Rails 7 allows GROUP BY and HAVING clauses with update_all and uses nested queries when doing DELETE with GROUP BY and HAVING clauses.
Interestingly, MySQL does not support using DELETE or UPDATE statements in combination with GROUP_BY or HAVING. To circumvent this, the PR uses nested queries.
DELETE FROM "users" WHERE "users"."id" IN (
SELECT "users"."id" FROM "users" INNER JOIN "votes" ON "votes"."user_id" = "users"."id" GROUP BY "users"."id" HAVING (count(votes.id) < 3))
) [["consistent", "t"]]
Recommend
-
9
Rails 7 adds the ability to schedule the query on the background thread pool Mar 31, 2021 , by Swaathi Kakarla 2 minute read
-
6
ActiveJob is used to enqueue and run the tasks in the background. But a job can fail because of many reasons. Say a network issue while communicating to the underlying datastore or non-availability of the datastore, etc. ActiveJob
-
17
A lot of times when working on web applications, a need arises to redirect a user without the user explicitly clicking on a link. For example, assume that a user has just created a post on an application. Once the post is created, it makes se...
-
7
Ahmad khattab Posted on Jan 15...
-
11
<?xml encoding="utf-8" ??>Introduction Sometimes, you might see more than one copy of the same record appearing in a MySQL database table. This usually happens after importing data from external...
-
8
Room is a database layer on top of an SQLite database that handles many tasks to make developers’ life easier. The equivalent of Room in iOS is
-
9
Rails adds the ability to prevent unwarranted shard swapping Mar 29, 2022 , by Swaathi Kakarla 2 minute read
-
8
Rails adds the ability to ignore tables in SQL schema dumps via regular expressions Jan 10, 2023 , by Prasanth Chaduvula 1...
-
11
What is Action cable Action Cable is a feature of the Ruby on Rails framework that provides real-time, bidirectional communication between a web server and its clients using WebSockets. It allows for the cre...
-
3
Delete Nodes having Greater Value on RightAugust 30, 2023 |940 ViewsPROBLEM OF THE DAY: 29/08/2023 | Delete Nodes having Greater Value on RightProblem of the Day, linked-list, Data Structure a...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK