17 messages in com.mysql.lists.mysqlRe: Inner join with left join
FromSent OnAttachments
Scott Haneda21 Feb 2006 22:47 
SGr...@unimin.com22 Feb 2006 06:11 
AM COMS22 Feb 2006 06:16 
SGr...@unimin.com22 Feb 2006 06:40 
Peter Brawley22 Feb 2006 08:15 
Scott Haneda22 Feb 2006 12:57 
Gordon Bruce22 Feb 2006 13:20 
SGr...@unimin.com22 Feb 2006 13:44 
Scott Haneda22 Feb 2006 17:07 
James Harvard22 Feb 2006 17:53 
Scott Haneda22 Feb 2006 18:38 
SGr...@unimin.com23 Feb 2006 06:51 
Scott Haneda23 Feb 2006 09:45 
SGr...@unimin.com23 Feb 2006 10:00 
SGr...@unimin.com23 Feb 2006 10:08 
Peter Brawley23 Feb 2006 12:19 
Peter Brawley24 Feb 2006 18:53 
Subject:Re: Inner join with left join
From:SGr...@unimin.com (SGr@unimin.com)
Date:02/23/2006 10:00:54 AM
List:com.mysql.lists.mysql

Sorry - I am trying to cut back to just 2 pots of coffee per day and I the lack of caffeine can make me a little fuzzy :-) Thank you for being patient with me.

You have a working query, we just need to convert your INNER JOINs to LEFT JOINs and move your join-specific WHERE conditions into the correct ON clauses

SELECT p.id, p.prod_name, sum(oi.quantity) as qty FROM products as p INNER JOIN order_items as oi ON (p.id = oi.product_id) INNER JOIN orders as o ON (o.id = oi.order_id) AND o.status NOT IN ('cancelled', 'pending', 'ghost') AND (o.created BETWEEN "2006-02-23 00:00:00" AND "2006-02-23 23:59:59") GROUP BY p.id, p.prod_name

By placing a restriction in the WHERE clause, you are requiring a value exist in that column after the JOINs are computed. That is why you have been throwing out all unsold products before you even got to the GROUP BY stage. You cannot group on values that aren't going to be there so I moved the two important columns of your SELECT statement back to the products table (SELECT p.id, p.prod_name ...) and made sure that those were the values you were grouping by.

Again, Thanks!

Shawn Green Database Administrator Unimin Corporation - Spruce Pine

Scott Haneda <lis@newgeo.com> wrote on 02/23/2006 12:45:28 PM:

You're right. It was a dumb cut-and-paste mistake.

LEFT JOIN orders as o on o.product_id = p.id

If fixing this doesn't give the correct results: What's missing? What's incorrect? Please help us to help you.

Orders does not have a product_id column. Let me see if I can explain this again, more better :-)

We have orders and order items, so for every orders, there are 1 or more order items, pretty basic. This SQL gets me almost what I want:

SELECT p.id, oi.prod_name, sum(oi.quantity) as qty FROM products as p INNER JOIN order_items as oi ON (p.id = oi.product_id) INNER JOIN orders as o ON (o.id = oi.order_id) WHERE o.status NOT IN ('cancelled', 'pending', 'ghost') AND (o.created BETWEEN "2006-02-23 00:00:00" AND "2006-02-23 23:59:59") GROUP BY oi.product_id

However, there are mysql> select count(*) from products; +----------+ | count(*) | +----------+ | 109 | +----------+ 1 row in set (0.00 sec)

So, 109 products in the products database, the first SQL above, will give me back a row for every order item that meets those criteria, however, it does not list products that were not ordered.

If I changed the first SQL to a date 10 years ago, I would get 0 rows, I want 109 where the sum() is all 0.

Basically, my client is wanting to see what products are selling, and which ones are not, in a certain date range, and I need to add in the status to limit it to only certain orders.

Running these three SQL's does what I want, with a temp table, but I find the solution kinda strange, and know it can be done in one go:

CREATE TEMPORARY TABLE prod_report SELECT p.id, oi.prod_name, sum(oi.quantity) as qty FROM products as p INNER JOIN order_items as oi ON (p.id = oi.product_id) INNER JOIN orders as o ON (o.id = oi.order_id) WHERE o.status NOT IN ('cancelled', 'pending', 'ghost') AND (o.created BETWEEN "2006-02-23 00:00:00" AND "2006-02-23 23:59:59") GROUP BY oi.product_id

INSERT INTO prod_report (SELECT id, prod_name, 0 FROM products)

SELECT * FROM prod_report GROUP BY id ORDER BY prod_name