简体   繁体   中英

SQL LEFT JOIN with COUNT that returns NULL values

I have two tables: one that stores the product id and one which stores total sales per product_id and per sale_date

Table Products

product_id
----------
1         
2         
3         

Table Sales

product_id |  sale_date | total
-----------+------------+-------
1          | 2017-01-01 |   1
1          | 2017-02-01 |   1
1          | 2017-03-01 |   1

There is no sales total for product 2 and product 3.

I would like to query the sales table in order to get 0 in front of the months where there is no sale for any product id. The result I would like to achieve is this:

product_id |  month     | total
-----------+------------+-------
1          | 2017-01    |   1
1          | 2017-02    |   1
1          | 2017-03    |   1
2          | 2017-01    |   0
2          | 2017-02    |   0
2          | 2017-03    |   0
3          | 2017-01    |   0
3          | 2017-02    |   0
3          | 2017-03    |   0

Right now what I do is this:

SELECT DATE_FORMAT(sale_date, "%m-%Y") as month,
       Products.product_id,
       COUNT(Sales.product_id) as total 

  FROM products Products 

LEFT OUTER JOIN sales Sales

             ON Sales.product_id = Products.product_id 

       GROUP BY Products.product_id, month

and what I get is:

product_id |  month     | total
-----------+------------+-------
1          | 2017-01    |   1
1          | 2017-02    |   1
1          | 2017-03    |   1
2          | NULL       |   0
3          | NULL       |   0

What should I modify to get a row for each month when there is no sale total for any product id? Thank you

Use a cross join to generate the rows, then left in to bring in the values:

select p.product_id, d.sales_date,
       coalesce(s.total, 0) as total
from products p cross join
     (select distinct sales_date from sales) d left join
     sales s
     on s.product_id = p.product_id and s.sales_date = d.sales_date
order by p.product_id, d.sales_date;

Note: This assumes that all the dates you want are in sales . I should point out that you can use another source for the dates, if you have one, or list them explicitly.

Could you give a try to this query:

select 
 distinct p.product_id, 
 DATE_FORMAT(sale_date, "%m-%Y") as month,
 if(p.product_id <> s.product_id, 0,total) as total 
 from products p, 
sales s 
order by p.product_id

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