Hi Benjamin,

Thanks for reading my message an taking some time to give some help/sugggestion..

First you are right that I should have written the query in a readable form..

You gave some comments:

> SELECT    brand.brandname,
>           SUM((productorders.quantity)*(productorders.price)) AS turnover
> FROM  orders
>           LEFT JOIN productorders ON productorders.orderid = orders.id
>           LEFT JOIN perfect_articles ON productorders.ordernr = articles.ordernr
>           LEFT JOIN products ON products.id = articles.id
>           LEFT JOIN brand ON products.brand = brand.id
> WHERE     productorders.date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), 
>'%Y-%m-%d')
>           AND productorders.date <= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 0 DAY), 
>'%Y-%m-%d')
>           AND orders.status != 2
> GROUP BY  brand.brandname
> ORDER BY  turnover asc
>
> Some comments:
>
> - Where is the table "articles" coming from? Did you mean
>   "perfect_articles"? If not, you have no restriction on this table.

Yes, sorry, missed that one.. All the tables I originally made the query for have the 
prefix perfect_ in front..
(perfect_articles, perfect_brand, perfect_productsorders.. I removed this to the make 
it shorter and not make the query
look more complicated than it is.. (To answer your question: I missed the one perfect_ 
you saw, this had to be removed....)

> - Where is the table "orders"? I assume you meant "productorders"?
No, I do a select .... from orders...
Further in the query productorders is linked to orders..
Productorders is also then linked to the database which contains all articles -> 
articles is linked to the products and products
linked to brand...
(Eg: the example: Microsoft (brand) -> Operating systems (products) -> Windows 95 
(articles)
The person orders a windows 95 package.. The subtotals, way of payment etc if stored 
in orders and all the articles he has ordered
is stored in productorders..
The reason why I needed to link productorders to orders is to have the option of 
ignoring all records in which the order.status =
2.. (This is an number which tells me
that the order has been cancelled)

(I hope you understand, this is very hard to explain I would be better of drawing a 
small chart..)

> - Do you really need LEFT JOINs instead of normal JOINs? At least the
>   effect of the LEFT JOIN with "productorders" is lost by using
>   "orders.status != 2" in the WHERE clause
>
> - You know that LEFT JOINs are usually slower than normal joins and
>   therefore should only be used when needed? (Additonally, the result
>   will differ in many cases)
Sorry, tell me I am dumb... I think that I understand SQL a bit, but I am by no ways 
an expert..
I do try to get my hands on books from which I can learn something, but joins and 
indexes are still an area from which I can learn a
lot of stuff..

In the past I always used a 'where' clause when joining stuff (eg: select 
apples.description, pears.description from apples, pears
where pears.id = apples.id order by apples.id etc etc
Then I got my hands on examples which used a left join examples.. I have never tried a 
normal join (sigh..), but thinking of it,
what is the difference between an left join and a normal join..??
(I will look at the chapter join in the mysql manual just now, so if I ask something 
dumb which is explained in the manual then skip
the answer..)
I use PHP to format my output, so maybe a left join has something to do with the order 
the columns are displayed which is no use for
me..??

> It doesn't matter if you use a ON clause instead of a WHERE clause
> with normal JOINS. The type of the JOIN does matter! And you cannot
> write LEFT JOINs with the constraint in the WHERE clause.
I understand what you say, only the last sentance I think I should go read the manual 
to understand it.. (you cannot write left
joins with the contraints?? in the where clause..)

I did an explain on the query like you suggested/asked: (Please bear in mind that you 
should think the 'perfect_' and
perfect_customer_ away for the above example...
These command (explain select...) are new to mee, but it looks like some useful 
information and that I can optimize a lot by adding
some extra indexes...????

Original Query:

SELECT perfect_brand.brandname,
            
Sum((perfect_customer_productorders.quantity)*(perfect_customer_productorders.price)) 
AS omzet
FROM perfect_customer_orders
            LEFT JOIN perfect_customer_productorders on 
perfect_customer_productorders.orderid = perfect_customer_orders.id
            LEFT JOIN perfect_articles on perfect_customer_productorders.ordernr = 
perfect_articles.ordernr
            LEFT JOIN perfect_products on perfect_products.id = perfect_articles.id
            LEFT JOIN perfect_brand on perfect_products.brand = perfect_brand.id
WHERE  (perfect_customer_productorders.date >= DATE_FORMAT( DATE_SUB( NOW() , INTERVAL 
30 DAY ) , '%Y-%m-%d' )
            AND perfect_customer_productorders.date <= DATE_FORMAT( DATE_SUB( NOW() , 
INTERVAL 0 DAY ) , '%Y-%m-%d' )
            AND perfect_customer_orders.status != 2)
GROUP BY perfect_brand.brandname
ORDER BY omzet asc


explain above query:  (Hope my tabs to get some layout stays intact)
I added an small gif to help when the following fails..
table                                                 type        possible_keys    key 
                key_len    ref
rows     Extra
perfect_customer_orders                   ALL
2585     where used
perfect_customer_productorders       ALL
4410     where used
perfect_articles                                  eq_ref    PRIMARY       PRIMARY      
 50
perfect_customer_productorders.ordernr   1
perfect_products                               ALL       PRIMARY
180
perfect_brand                                   ALL       PRIMARY,id
16

show index from perfect_customer_orders
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_customer_orders   0   PRIMARY   1   id   A   2585
perfect_customer_orders   1   id   1   id   A

show index from perfect_customer_productorders
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_customer_productorders   0   PRIMARY   1   id   A   4410
perfect_customer_productorders   1   id   1   id   A

show index from perfect_customer_productorders
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_customer_productorders   0   PRIMARY   1   id   A   4410
perfect_customer_productorders   1   id   1   id   A

show index from perfect_articles
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_articles   0   PRIMARY   1   ordernr   A   314
perfect_articles   1   nr   1   nr   A

show index from perfect_products
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_products   0   PRIMARY   1   id   A   180

show index from perfect_brand
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part
perfect_brand   0   PRIMARY   1   id   A   16

I am also going to do some reading myself on the normal join, thanks for your info...

Bye Bye
David


----- Original Message -----
From: "Benjamin Pflugmann" <[EMAIL PROTECTED]>
To: "David Bouw" <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Sent: Friday, July 20, 2001 7:11 PM
Subject: Re: Left Join very sloooowwww..


> Hello.
>
> [...]
> > Here is the query
> >
>
> [query reformatted... btw, it would have been nice if you had done this at first]
> SELECT    brand.brandname,
>           SUM((productorders.quantity)*(productorders.price)) AS turnover
> FROM      orders
>           LEFT JOIN productorders ON productorders.orderid = orders.id
>           LEFT JOIN perfect_articles ON productorders.ordernr = articles.ordernr
>           LEFT JOIN products ON products.id = articles.id
>           LEFT JOIN brand ON products.brand = brand.id
> WHERE     productorders.date >= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 30 DAY), 
>'%Y-%m-%d')
>           AND productorders.date <= DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 0 DAY), 
>'%Y-%m-%d')
>           AND orders.status != 2
> GROUP BY  brand.brandname
> ORDER BY  turnover asc
>
> Some comments:
>
> - Where is the table "articles" coming from? Did you mean
>   "perfect_articles"? If not, you have no restriction on this table.
>
> - Where is the table "orders"? I assume you meant "productorders"?
>
> - Do you really need LEFT JOINs instead of normal JOINs? At least the
>   effect of the LEFT JOIN with "productorders" is lost by using
>   "orders.status != 2" in the WHERE clause
>
> - You know that LEFT JOINs are usually slower than normal joins and
>   therefore should only be used when needed? (Additonally, the result
>   will differ in many cases)
>
> [...]
> > I need to do the above query about 4 times for different intervals and in this 
>case it then takes about 15 minutes to
complete...
> > (Pentium III 800 machine with 128 MB)
> [...]
>
> We need to see the output of
>
> EXPLAIN SELECT ...
> SHOW INDEX FROM brand
> SHOW INDEX FROM productorders
> SHOW INDEX FROM perfect_articles
> SHOW INDEX FROM products
> SHOW INDEX FROM orders
>
> > It looks that as soon as if I start to link a table with more than
> > 1000 records the machine is having a hard time.. Is it better to use
> > a where clause to link the tables..??
>
> It doesn't matter if you use a ON clause instead of a WHERE clause
> with normal JOINS. The type of the JOIN does matter! And you cannot
> write LEFT JOINs with the constraint in the WHERE clause.
>
> Bye,
>
>         Benjamin.
>
>

---------------------------------------------------------------------
Before posting, please check:
   http://www.mysql.com/manual.php   (the manual)
   http://lists.mysql.com/           (the list archive)

To request this thread, e-mail <[EMAIL PROTECTED]>
To unsubscribe, e-mail <[EMAIL PROTECTED]>
Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php

Reply via email to