mirror of
https://github.com/jbranchaud/til
synced 2026-01-02 22:58:01 +00:00
Add Find Records With Multiple Associated Records as a Rails til
This commit is contained in:
@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
|
||||
|
||||
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
|
||||
|
||||
_1173 TILs and counting..._
|
||||
_1174 TILs and counting..._
|
||||
|
||||
---
|
||||
|
||||
@@ -705,6 +705,7 @@ _1173 TILs and counting..._
|
||||
- [Disambiguate Where In A Joined Relation](rails/disambiguate-where-in-a-joined-relation.md)
|
||||
- [Ensure Migrations Use The Latest Schema](rails/ensure-migrations-use-the-latest-schema.md)
|
||||
- [Find Or Create A Record With FactoryBot](rails/find-or-create-a-record-with-factory-bot.md)
|
||||
- [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md)
|
||||
- [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md)
|
||||
- [Generating And Executing SQL](rails/generating-and-executing-sql.md)
|
||||
- [Get An Array Of Values From The Database](rails/get-an-array-of-values-from-the-database.md)
|
||||
|
||||
37
rails/find-records-with-multiple-associated-records.md
Normal file
37
rails/find-records-with-multiple-associated-records.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Find Records With Multiple Associated Records
|
||||
|
||||
Relational data often involves a table that has a one-to-many relationship with
|
||||
another table. For instance, a team can be made up of many members. A question
|
||||
we may want to ask of that data is, what are the records (`teams`) that are
|
||||
associated with more than one of this other table (`members`).
|
||||
|
||||
With a few SQL features that are supported by ActiveRecord's query syntax, we
|
||||
can answer that question.
|
||||
|
||||
To make it interesting, let's say we are trying to answer the question, "what
|
||||
are the teams that have multiple _active_ members?"
|
||||
|
||||
```ruby
|
||||
Team
|
||||
.joins(:members)
|
||||
.where(members: { status: 'active' })
|
||||
.having("count(*) >= 2")
|
||||
.group("teams.id")
|
||||
.count
|
||||
|
||||
=> {
|
||||
123 => 2,
|
||||
345 => 3,
|
||||
567 => 2,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
That final `.count` is going to manifest as a `count(*)` in the `select`
|
||||
clause. That `count(*)` aggregate combined with the `group("teams.id")` is
|
||||
going to flatten the results to be unique by team ID. Then the `having` clause
|
||||
will filter out all teams with a member count less than 2. And before that, the
|
||||
where will cut down the members to only those that are `active`.
|
||||
|
||||
If you just want the IDs, you can tack a `#keys` call onto the end of that
|
||||
query result.
|
||||
Reference in New Issue
Block a user