I have two tables (tblReps
and tblDailyWorkingTime
). The tblReps
table, i.e., the first one, returns 37 rows, but when I JOIN it with the second table I get 36 rows as the second table only has 36 rows that match the first table.
How do I go about getting the 37 rows back with a NULL result for the row that was not matched?
Here is the query that I have so far:
SELECT
tblReps.[sName] AS 'RepName',
tblReps.sNote AS 'Type',
RIGHT(CAST(tblDaily.sDateAndTimeStart AS smalldatetime), 8) AS 'DayStarted'
FROM
[tblRepresentatives] AS tblReps
FULL OUTER JOIN
tblDailyWorkingTime AS tblDaily ON tblDaily.sRepresentativeCode = tblReps.sCode
WHERE
tblDaily.sDate = CAST(GETDATE() AS DATE)
AND tblReps.[sActive] = 'True'
Best Answer
First of all, the correct type of join to use in this case is a left join:
In your specific case, you could still use
FULL
because this condition inWHERE
would turn it into a left join anyway:But it is better to express the intent accurately.
The same effect that turns your full join into a left join is actually responsible for the missing 37th row that you expected. More specifically, this other
WHERE
condition:transforms your join further into an inner join. That is why the 37th row is missing from the output.
The reason for that happening is this. The
FROM
clause returns a null intblDaily.sDate
for the unmatched row. Because theWHERE
clause logically executes after theFROM
, the above-mentioned predicate excludes the unmatched row, sinceNULL = CAST(GETDATE() AS DATE)
does not evaluate to True.What you need to do instead is move the
sDate
condition to theON
subclause:That way the right-hand side of the join is filtered on
tblDaily.sDate = CAST(GETDATE() AS DATE)
before the join takes place. Consequently, the query will return the expected 37 rows fromtblReps
complemented either with matching data fromtblDaily
or with nulls.