A look at how postgREST does joins and the gotchas involved
Unspecified: left joins
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts(text)
A regular PostgREST embed.
!inner
for inner joins
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts!inner(text)
Only include rows that exist in both tables.
Left join with condition
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts(text)&posts.text=hello
Filters results in the embedded table (posts
). Importantly, this will not filter the top-level users
at all. Use inner joins with conditions for that.
Inner join with condition
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts!inner(text)&posts.text=hello
Filters results in the embedded table (posts
) while also only keeping users
that have at least one embedded post
.
Null condition for anti-joins
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts()&posts=is.null
Skip users
for which there exists a post
.
count
for an embedded resource count
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts(count)
When count
is the only column for an embedded resource, PostgREST returns the number of items in the relationship.
While this cannot be directly combined with actually returning embedded relationships data, you can embed the same table twice:
PostgREST
Supabase/postgrest-js
GET /users?select=name,posts(text),post_count:posts(count)