versilov
Sub-selects in ecto queries
How can I write this query in Ecto?
SELECT
*,
(SELECT COUNT(o.id) FROM tenant_versilov.orders o
LEFT OUTER JOIN tenant_versilov.shipments s ON s.order_id = o.id
WHERE o.company_id = c.id AND s.id IS NULL AND NOT o.archived) orders_count,
(SELECT COUNT(s.id) FROM tenant_versilov.shipments s
LEFT OUTER JOIN tenant_versilov.orders o ON s.order_id = o.id
WHERE o.company_id = c.id AND s.batch_id IS NULL) shipments_count
FROM tenant_versilov.companies c
WHERE c.active = TRUE;
The closest approach is to use select_merge with fragments, but fragments do not allow to interpolate strings to set schemas:
query
|> select_merge([c], %{
shipments_count:
fragment(
"(SELECT COUNT(s.id) FROM tenant_versilov.shipments s
LEFT OUTER JOIN tenant_versilov.orders o ON s.order_id = o.id
WHERE o.company_id = c0.id AND s.batch_id IS NULL)"
)
Marked As Solved
versilov
With minor modifications it worked, thanks!
Had to add group_by and coalesce to deal with nil count values.
Here is the final working query:
orders_query =
from(o in Order,
left_join: s in assoc(o, :shipments),
where: not o.archived and is_nil(s.id),
group_by: o.company_id,
select: %{company_id: o.company_id, count: count()}
)
shipments_query =
from(s in Shipment,
inner_join: o in assoc(s, :order),
where: is_nil(s.batch_id),
group_by: o.company_id,
select: %{company_id: o.company_id, count: count()}
)
Company
|> filter_by_user(user)
|> only_active(true)
|> join(:left, [c], o in subquery(orders_query), on: o.company_id == c.id)
|> join(:left, [c], s in subquery(shipments_query), on: s.company_id == c.id)
|> group_by([c, o, s], [c.id, o.count, s.count])
|> select_merge([c, o, s], %{
orders_count: coalesce(o.count, 0),
shipments_count: coalesce(s.count, 0)
})
|> Repo.all(prefix: tenant)
3
Also Liked
hauleth
What you probably want is something like:
SELECT
c.*,
orders.count,
s.count
FROM companies c
INNER JOIN (SELECT o.company_id company_id, COUNT(*) count
FROM orders o
LEFT OUTER JOIN shipments s ON s.order_id = o.id
WHERE s.id IS NULL AND NOT o.archived
GROUP BY o.company_id) orders
ON orders.company_id = c.id
-- and so on
So in Elixir it would be like:
orders_query =
from o in Order,
left_outer_join: s in assoc(o, :shipments),
where: not o.archived and is_nil(s.id),
group_by: o.company_id,
select: %{id: o.company_id, count: count()}
shipments_query =
from s in Shipment,
left_inner_join: o in assoc(sh, :order),
where: is_nil(s.batch_id),
select: %{id: o.company_id, count: count()}
from c in Company,
left_inner_join: o in subquery(orders_query), on: o.id == c.id,
left_inner_join: s in subquery(shipments_query), on: s.id == c.id,
select_merge: %{orders_count: o.count, shipments_count: s.count}
5
Popular in Questions
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Hello, how can I check the Phoenix version ?
Thanks !
New
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
Other popular topics
Hello!
Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Phoenix 1.4.0 released
Phoenix 1.4 is out! This release ships with exciting new features, most notably
with HTTP2 support, improved deve...
New
Hey,
Just curious what are the main benefits of Elixir compared to Clojure?
When is Elixir more useful than Clojure and vice versa?
Th...
New
After calling mix ecto.create I get this error:
17:00:32.162 [error] GenServer #PID<0.412.0> terminating
** (Postgrex.Error) FATAL...
New
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service.
Currently when I de...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









