Solved

SQL - Left joins and where clauses

Posted on 2009-05-06
9
177 Views
Last Modified: 2012-05-06
Hi there,

A general question really .. if I have some left joins in my sql, do I need to put all the conditions in the main where clause in each left join? Code sample attached,

Thankyou,

Roger
0
Comment
Question by:Rogero
  • 6
  • 3
9 Comments
 

Author Comment

by:Rogero
ID: 24312270
File attached
0
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 24312276
nothing attached so far, but anyhow:


SELECT * FROM tableA a LEFT JOIN TableB b ON a.key = b.key WHERE b.somefield = somevalue
 
is no longer a LEFT JOIN, but a INNER JOIN, aka, will work as if you wrote:
SELECT * FROM tableA a INNER JOIN TableB b ON a.key = b.key WHERE b.somefield = somevalue
 
correct way:
SELECT * FROM tableA a LEFT JOIN TableB b ON a.key = b.key AND b.somefield = somevalue
 
UNLESS you write this:
SELECT * FROM tableA a LEFT JOIN TableB b ON a.key = b.key WHERE b.key IS NULL
to find only those record in tableA that are not in table B

Open in new window

0
 

Author Comment

by:Rogero
ID: 24312305
Here is my code ..

SELECT             
      d.cname,
      m.subcode,
      count(distinct m.invoiceno) as InvTotalCount,
      count(distinct m1.Invoiceno) as InvCompletecount,
      count(distinct m2.Invoiceno) as InvPassCount,
      count(distinct m3.Invoiceno) as InvFailCount,
      sum(case when m.qastatus is not null then 1 else 0 end) as mainmeasurecount,
      sum(case when m.qastatus in ('o', 'p') then 1 else 0 end) as mainmeasurepasscount,
      sum(case when m.qastatus = 'f' then 1 else 0 end) as mainmeasurefailcount
FROM             
      dbo.FCMEASURES m
      JOIN dbo.FCJOB j  on j.invoiceno = m.invoiceno
      JOIN dbo.KIMSGROUPS k  on k.code = m.servicecode
      JOIN dbo.FCDIST d  on d.code = m.subhocode
      LEFT JOIN dbo.fcmeasures m1  on j.invoiceno = m1.invoiceno       and m1.servicegrp = 19
                                                      and m1.status = 'A'
                                                      and m1.completedate is not null
      LEFT JOIN dbo.fcmeasures m2  on j.invoiceno = m2.invoiceno       and m2.servicegrp = 19
                                                      and m2.status = 'A'
                                                      and m2.completedate is not null
                                                      and m2.qastatus in ('p', 'o')
      LEFT JOIN dbo.fcmeasures m3  on j.invoiceno = m3.invoiceno       and m3.servicegrp = 19
                                                      and m3.status = 'A'
                                                      and m3.completedate is not null
                                                      and m3.qastatus not in ('p', 'o')
WHERE             
      k.main = 'Y'
      and m.completedate is not null
      and m.canceldate is null

GROUP BY       
      m.subhocode, d.cname
order by 1

0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 

Author Comment

by:Rogero
ID: 24312339
do i need to put the k.main = 'Y' into each left join? I would need to add more tables to do this in each left join .. or does the k.main = 'Y' in the main where clause handle it all?
0
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 24312395
>do i need to put the k.main = 'Y' into each left join?
no, because k table is not left joined, but inner joined

you could nevertheless move that condition to the JOIN condition
SELECT             
      d.cname,
      m.subcode,
      count(distinct m.invoiceno) as InvTotalCount,
      count(distinct m1.Invoiceno) as InvCompletecount,
      count(distinct m2.Invoiceno) as InvPassCount,
      count(distinct m3.Invoiceno) as InvFailCount,
      sum(case when m.qastatus is not null then 1 else 0 end) as mainmeasurecount,
      sum(case when m.qastatus in ('o', 'p') then 1 else 0 end) as mainmeasurepasscount,
      sum(case when m.qastatus = 'f' then 1 else 0 end) as mainmeasurefailcount
FROM             
      dbo.FCMEASURES m 
      JOIN dbo.FCJOB j  on j.invoiceno = m.invoiceno
      JOIN dbo.KIMSGROUPS k  on k.code = m.servicecode and k.main = 'Y' 
      JOIN dbo.FCDIST d  on d.code = m.subhocode
      LEFT JOIN dbo.fcmeasures m1  on j.invoiceno = m1.invoiceno       and m1.servicegrp = 19 
                                                      and m1.status = 'A' 
                                                      and m1.completedate is not null 
      LEFT JOIN dbo.fcmeasures m2  on j.invoiceno = m2.invoiceno       and m2.servicegrp = 19 
                                                      and m2.status = 'A' 
                                                      and m2.completedate is not null 
                                                      and m2.qastatus in ('p', 'o')
      LEFT JOIN dbo.fcmeasures m3  on j.invoiceno = m3.invoiceno       and m3.servicegrp = 19 
                                                      and m3.status = 'A' 
                                                      and m3.completedate is not null
                                                      and m3.qastatus not in ('p', 'o')
WHERE m.completedate is not null 
  AND m.canceldate is null
 
GROUP BY       
      m.subhocode, d.cname
order by 1

Open in new window

0
 

Author Comment

by:Rogero
ID: 24312414
Thanks Angellll, that helps.

Can you see why I have the left joins there (so I can get the m1, m2 qnd m3 counts correctly) .. is there a better way to write this qry?
0
 

Author Comment

by:Rogero
ID: 24312535
The m1 count should equal m2+m3 counts but unfortunately the code is not returning this result
0
 
LVL 143

Accepted Solution

by:
Guy Hengel [angelIII / a3] earned 500 total points
ID: 24312570
when you join to several tables, and need to count both of them apart, you have to FIRST group by in a subquery, and then join.

chinese?

here we go:
SELECT             
      d.cname,
      m.subcode,
      max(m1.InvCompletecount) InvCompletecount, 
      ...
 
      sum(case when m.qastatus is not null then 1 else 0 end) as mainmeasurecount,
      sum(case when m.qastatus in ('o', 'p') then 1 else 0 end) as mainmeasurepasscount,
      sum(case when m.qastatus = 'f' then 1 else 0 end) as mainmeasurefailcount
FROM             
      dbo.FCMEASURES m 
      JOIN dbo.FCJOB j  on j.invoiceno = m.invoiceno
      JOIN dbo.KIMSGROUPS k  on k.code = m.servicecode and k.main = 'Y' 
      JOIN dbo.FCDIST d  on d.code = m.subhocode
      LEFT JOIN ( SELECT invoiceno   
                       , count(*) InvCompletecount
                   FROM dbo.fcmeasures m1  
                  WHERE m1.servicegrp = 19 
                    and m1.status = 'A' 
                    and m1.completedate is not null 
                 ) m1 
           ON j.invoiceno = m1.invoiceno       
       .... 
WHERE m.completedate is not null 
  AND m.canceldate is null
 
GROUP BY       
      m.subhocode, d.cname
order by 1

Open in new window

0
 

Author Closing Comment

by:Rogero
ID: 31578361
Thanks this has helped
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

As they say in love and is true in SQL: you can sum some Data some of the time, but you can't always aggregate all Data all the time! Introduction: By the end of this Article it is my intention to bring the meaning and value of the above quote to…
'Between' is such a common word we rarely think about it but in SQL it has a very specific definition we should be aware of. While most database vendors will have their own unique phrases to describe it (see references at end) the concept in common …
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question