My comments imbedded....

Scott Hamm <[EMAIL PROTECTED]> wrote on 05/03/2005 03:16:31 PM:

>    Since I'm learning about Left joins and am trying to figure out a way
> to quickly gather info from Database all at once, here is the SQL
> statement.  Please give me feedback how I should improve it for better
> performance.  There are around 10 users that will hit database like
> this along with other left joins ever minute.  Thanks in advance:
> 

First, THANK YOU for formatting your query.

> SELECT 
>    QA.ID,
>    Brands.Brand,
>    QA.KeyDate,
>    A2.LastName + ', ' + A2.FirstName as Reviewer, 
>    A1.LastName + ', ' + A1.FirstName as Operator, 
>    Batch.[order], 
>    Errortypes.[Description], 
>    ErrorTypes.points,
>    Batch.Comments,

These next two statements have the potential to be evaluated once per row. 
However, you are not running a subquery that uses any values from the 
outer query so you are in essence computing constants for these next two 
columns.

>    (SELECT 
>       sum(Errortypes.points) 
>    FROM 
>       ErrorTypes,QAErrors,Batch,QA 
>    WHERE 
>       Errortypes.Id=QAErrors.ErrorTypeID 
>    AND 
>       QAErrors.ID=Batch.QEID 
>    AND 
>       Batch.QAID=QA.ID 
>    AND 
>       QA.Batch='464005807') as points,
>    (SELECT 
>       count(*)*100 
>    FROM 
>       Batch,QA 
>    WHERE 
>       Batch.QAID=QA.ID 
>    AND 
>       QA.Batch='464005807') as total

You say you are learning about LEFT joins (which, btw, look just like 
INNER joins) but you aren't using INNER JOINS? You are using crappy 
Oracle-style comma-separated table lists (ugggh). (It's not "wrong" to do 
this, it's just my personal pet peeve)

> FROM 
>    Brands,Associates A1, Associates A2,QA 
> Left Join 
>    Batch 
>    ON 
>    Batch.QAID=QA.ID 
> Left Join 
>    QAErrors 
>    ON 
>    QAErrors.ID=Batch.QEID
> Left Join 
>    Errortypes 
>    On 
>    ErrorTypes.id=QAErrors.ErrorTypeID 
> WHERE 
>    QA.Batch='464005807' 
> AND 
>    A1.ID=QA.OperatorID
> AND
>    A2.ID=QA.QAID
> AND
>    Brands.ID=QA.BrandID;
> 
> 
> RESULT (delimited by ,):
> 
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770323,Error in Name,8.0,last name mispelled,24.0,600
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770323,Error in Address,8.0,blvd mispelled,24.0,600
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770324,Error in Address,8.0,BLVD MISSPELLED,24.0,600
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770325,NULL,NULL,NULL,24.0,600
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770322,NULL,NULL,NULL,24.0,600
> 100528,Imaged G-5,2005-05-03 00:00:00,Cahall, Margaret,Custis,
> Teresa,244770321,NULL,NULL,NULL,24.0,600
<snip>

See how the last two columns are always the same values. If that is really 
what you wanted to compute for those columns, there is an easier way to do 
it. Use variables to hold the results of computin those values then just 
add them to the SELECT clause of your final query. That way you are 
certain that the engine only computes them values once.

I would modify your query to look like this (assuming that the Batch field 
on the QA table is really a numeric value and not a string):

SELECT @points := sum(Errortypes.points) 
FROM ErrorTypes
INNER JOIN QAErrors
        ON Errortypes.Id=QAErrors.ErrorTypeID 
INNER JOIN Batch
        ON QAErrors.ID=Batch.QEID 
INNER JOIN QA 
        ON Batch.QAID=QA.ID 
WHERE QA.Batch=464005807;

SELECT @total := count(1)*100
FROM Batch
INNER JOIN QA 
        ON Batch.QAID=QA.ID 
WHERE QA.Batch=464005807;

SELECT 
        QA.`ID`,
        Brands.`Brand`,
        QA.`KeyDate`,
        CONCAT(A2.`LastName`,', ',A2.`FirstName`) as Reviewer, 
        CONCAT(A1.`LastName`,', ',A1.`FirstName`) as Operator, 
        Batch.`order`, 
        Errortypes.`Description`, 
        ErrorTypes.`points`,
        Batch.`Comments`,
        @points as points,
        @total as total
FROM Brands
INNER JOIN QA
        ON Brands.ID=QA.BrandID 
INNER JOIN Associates A1
        ON A1.ID=QA.OperatorID
INNER JOIN Associates A2
        ON A2.ID=QA.QAID
Left Join Batch 
        ON Batch.QAID=QA.ID 
Left Join QAErrors 
        ON QAErrors.ID=Batch.QEID
Left Join Errortypes 
        ON ErrorTypes.id=QAErrors.ErrorTypeID 
WHERE QA.Batch=464005807;

(BTW - I think the original query came from M$ SQL Server. Did it?)

Without knowing more about what it is you are trying to get with this 
query, it's hard to make a better guess on how to make it work. The main 
issues I saw were:

a) abusing subqueries when variables were more appropriate.
b) using [] instead of `` to delimit reserved field names (not supported 
by MySQL).
c) using + as a string concatenator (not supported by MySQL).
d) using the comma-separated form of implicit inner joins and not fully 
declared, explicit INNER JOIN clauses.


Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine

Reply via email to