简体   繁体   中英

SQL: Join two tables, take all row and set default value

I am new to SQL and I don't know correct word to search currently.

I have a first table like this - it has 5 rows.

SELECT 
    tFinal2.region, COUNT(newsfeed_id) AS comment 
FROM
    (SELECT *  
     FROM
         ((SELECT *
           FROM public.newsfeed_comment) AS T1
          INNER JOIN
              (SELECT * FROM public.newsfeed) AS T2 ON T1.newsfeed_id = T2.seq) AS tFinal1) AS tFinal2
GROUP BY 
    tFinal2.region

在此处输入图片说明

and this is my second table:

SELECT tFinal2.region, COUNT(newsfeed_id) AS media 
FROM
    (SELECT *
     FROM
         ((SELECT *
           FROM public.newsfeed_media) AS T1
          INNER JOIN
          (SELECT * FROM public.newsfeed) AS T2 T1.newsfeed_id = T2.seq) AS tFinal1) AS tFinal2
GROUP BY 
    tFinal2.region

在此处输入图片说明

The second table has 6 rows.

So, if I simply join the 5 rows from table #1 and 6 rows from table #2 using either inner join, outer join, etc, it will only return 5 rows.

How can I join so that it will return all rows and set default value as zero for missing values? (I also cannot know which table has more rows. It can change from time to time and I cannot do left, right join).

I think you want:

select nf.region, coalesce(sum(num_comments), 0) as num_comments,
       coalesce(sum(num_media), 0) as num_media
from public.newsfeed nf left join
     (select c.newsfeed_id, count(*) as num_comments
      from public.newsfeed_comment c
      group by c.newsfeed_id
     ) c
     on nf.seq = c.newsfeed_id left join
     (select m.newsfeed_id, count(*) as num_media
      from public.newsfeed_media m
      group by m.newsfeed_id
     ) m
     on nf.seq = m.newsfeed_id
group by nf.region;

Notes:

  • The results from a query are not a "table", they are a result set, which can be used a subquery in another query.
  • Use table aliases that are related to the table names. This makes it easier to follow queries.
  • You want to aggregate along two different dimensions (media and comments). You need to aggregate separately to avoid Cartesian products).
  • To avoid NULL values, use coalesce() .
  • Do not use (select * from . . . ) subqueries. These are just harder to write and read. And in some databases, they can affect performance.

Use left join and coalesce() function for replacing missing value with 0

select tFinal2.region, coalesce(count(newsfeed_id),0) as comment from (
    select * from (
    (SELECT *
    FROM public.newsfeed_comment) as T1
    left join 
    (SELECT * from public.newsfeed) as T2
    on T1.newsfeed_id = T2.seq) as tFinal1
    ) as tFinal2
    group by tFinal2.region

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM