views:

159

answers:

3

I have two tables, tblEntities and tblScheduling.

tblEntities:

EntityID  ShortName          Active
1         Dirtville          1
2         Goldtown           1
3         Blackston          0
4         Cornfelt           1
5         Vick               1

tblScheduling:

ScheduleID EntityID SchedulingYearID
1          1        20
2          1        21
3          2        20
4          3        19
5          5        20

I need a query that will show ALL ACTIVE Entities and their schedule information for a particular ScheduleYearID.

Output should look like (the desired SchedulingYearID in this case is 20):

EntityID ScheduleID
1        1
2        3
4        NULL
5        5

The query that I have written so far is:

SELECT     tblEntities.EntityID, tblEntities.ShortName, tblScheduling.ScheduleID
FROM         tblScheduling RIGHT OUTER JOIN
                      tblEntities ON tblScheduling.EntityID = tblEntities.EntityID
WHERE     (tblScheduling.SchedulingYearID = @SchedulingYearID) 
AND (tblEntities.Active = 1)
ORDER BY tblEntities.EntityID

My problem is that using this query it will not include active entities without schedule information (such as EntityID 4 in the example above). I can write the query to display all active entities and their schedule status fine, but once I start limiting it via the SchedulingYearID I lose those particular entities.

Are there any solutions that I am obviously missing without having to resort to subqueries, cursors, etc.? If not it's not a big deal, I just feel like I am missing something simple here.

+6  A: 

Try this... Join conditions are evaluated to produce the intermediate Join result set, and then, (for an outer join), all the rows from the "Outer" side are added back in before moving on... Where conditions are evaluated after all joins are done...

SELECT E.EntityID, E.ShortName, S.ScheduleID
FROM  tblEntities E 
     Left Join tblScheduling S 
        ON S.EntityID = E.EntityID
           And S.SchedulingYearID = @SchedulingYearID 
WHERE E.Active = 1
ORDER BY E.EntityID

I change your join order cause I prefer left joins... but it doesn't matter

Charles Bretana
I knew it had to be something simple. I had previously tried a left join as well but it gave me the same problem. I see the actual problem was that I didn't put the SchedulingYearID check in the join clause where it should have gone instead of the where. Thanks a lot.
TheTXI
Yr very welcome.. Good Luck! and try using table alises (as shown) they tend to make your sql terser and, mostly, more readable...
Charles Bretana
A: 

It's your conditions in the where clause: (tblScheduling.SchedulingYearID = @SchedulingYearID)

when there is no tblScheduling info this wil always fail. Add

(((tblScheduling.SchedulingYearID = @SchedulingYearID) OR (tblScheduling.SchedulingYearID is null) )

or wathever null condition checking your DB uses.

Glenner003
A: 

I think the trouble is that the WHERE clause is filtering out the rows where SchedulingYearID is null. So don't.

SELECT tblEntities.EntityID, tblEntities.ShortName, tblScheduling.ScheduleID
    FROM tblScheduling RIGHT OUTER JOIN
         tblEntities ON tblScheduling.EntityID = tblEntities.EntityID
    WHERE (tblScheduling.SchedulingYearID = @SchedulingYearID OR
           tblScheduling.SchedulingYearID IS NULL) 
      AND (tblEntities.Active = 1)
    ORDER BY tblEntities.EntityID;
Jonathan Leffler
I think that "WHERE" should be replaced with "HAVING". You are looking for nulls in tblScheduling.SchedulingYearID but there are no nulls there. "HAVING" OTOH will find the nulls that are introduced by the join.
finnw
@finnw: the result table from tblScheduling RIGHT JOIN tblEntities contains nulls for the tblScheduling values where there's no match in tblEntities; the WHERE clause in the original query only selects rows where the correct values is in the SchedulingYearID, and NULL is not the correct 'value'.
Jonathan Leffler
@finnw: that said, I think it is better to do as Charles Bretana did and do the filtering in the RIGHT JOIN. This result is equivalent, though not quite as tidy.
Jonathan Leffler