versilov

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

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)

Also Liked

hauleth

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}

Where Next?

Popular in Questions Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
Harrisonl
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
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement