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 <[EMAIL PROTECTED]> 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
> -- 
> -------------------------------------------------------------
> Scott Haneda                                Tel: 415.898.2602
> <http://www.newgeo.com>                     Novato, CA U.S.A.
> 
> 

Reply via email to