Вопрос

I am struggling with my statement in PostgreSQL. I have 3 tables:

tbl - flags (labeled as a)
a.email

tbl - accounts (labeled as b)
b.id
b.email

tbl - foo (labeled as c)
c.account_id
c.total

My sql statement looks like:

select a.email, sum(c.total)
from flags a, accounts b, foo c
where a.email = b.email and b.id = c.account_id

This statement works but there could be some accounts who does not have an account or total amount either. Well, this statement does not make sense, because there are several a.emails in flags a, which don’t have any c.total record. And also there are several b.emails in accounts b, who doesn’t have any record in c.total.

My desired output: email - sum(i.total)

foo@foo.com      5666
kjkj@kjaksd.com  882
hello@world.com  23122
mac@toast.com    0 -- mac@toast.com doesn’t have account or any total

So is it possible to check if a record exist in accounts compare to flags? And if so, let’s prompt total amount and if not, let’s prompt 0.

Это было полезно?

Решение

  • First, the query you have is not valid. I assume you omitted the GROUP BY a.email when posting the question. You also alias foo as c but then you reference to i.total.

  • Now for the missing results, it's because you are using (implicit) inner joins. That they are implicit, it doesn't affect results. But when using explicit joins, it's easy to change them from INNER to LEFT join.
    So by doing a LEFT JOIN b we keep results from a that have no matching row in b and by doing b LEFT JOIN c we keep results from b that have no matching row in c.

  • The query finally looks like this (adding COALESCE() so we get zeros and not nulls for the emails that have no account or total):

    select a.email, 
           coalesce(sum(c.total), 0) as sum_total
    from flags as a
      left join accounts as b
        on a.email = b.email              -- join condition
      left join foo as c
        on b.id = c.account_id            -- join condition
    group by a.email ;
    

Другие советы

Use a subquery to calculate total:

select a.email, 
       coalesce((select sum(c.total)
                 from   accounts b
                 inner join foo c
                 on b.id = c.account
                 where a.email = b.email), 0) total
from   flags a

Use COALESCE to take care of NULL values.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top