LEFT OUTER JOIN with a WHERE clause
I have two tables. indRailType
contains a list of the names paired with an ID value that I use in other tables to indicate the rail type. WO_BreakerRail
contains a date column and a rail code column that corresponds to the same code in indRailType
and some other data. There's a row in WO_BreakerRail
for any activity on each rail type, for every date. So I could have 3 rows dated for 3/19/2010
, each row indicates a different rail code, and what happened.
When I use the following LEFT OUTER JOIN
, I get a table with all the types of rail, with nulls in the rows where nothing happened on the 19th. Now, this is only working because I only have one date represented in my WO_BreakerRail
table right now, the 19th. When I add more rows with different dates, things will go haywire.
This is my SQL statement, which right now gives me exactly the results I want:
SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces,
WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged,
WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail
ON indRailType.RailCode = WO_BreakerRail.RailCode
Now, when I add in a WHERE WO_BreakerRail.Date = @Date
clause I 开发者_如何学编程lose all the rows in the JOIN
which nothing happened. I don't want that. From reading up, it sounds like a FULL OUTER JOIN
is what I want, but SQL Server Compact Edition doesn't support FULL OUTER JOIN
s. Is there a way around this, or am I looking for something else entirely?
Try:
SELECT WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces,
WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged,
WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode
AND WO_BreakerRail.Date = @Date
Thus adding AND WO_BreakerRail.Date = @Date
onto the join
The predicate condition needs to be in the On
clause for the join, not in the where clause. The way Outer joins work, is after the join conditions are analyzed, all the rows from the "outer side" that do not match the inner side are added back in.... But this all happens before the where clause is processed. So if the where clause predicate filters on an attribute from the outer side of an outer join, all those rows will be removed again... (They are all null). Put the predicate in the join condition instead, then it will get evaluated before the missing rows are added back in...
SELECT b.ID, t.RailType, b.CreatedPieces,
b.OutsideSource, b.Charged, b.Rejected,
b.RejectedToCrop
FROM indRailType t
LEFT JOIN WO_BreakerRail b
ON t.RailCode = b.RailCode
And b.Date = @Date
You could use this where clause:
WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL
add the WO_BreakerRail.Date = @Date
on the LEFT OUTER JOIN
statement and not the WHERE
:
SELECT
WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode AND WO_BreakerRail.Date = @Date
or you can add it to the WHERE:
SELECT
WO_BreakerRail.ID, indRailType.RailType, WO_BreakerRail.CreatedPieces, WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged, WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType
LEFT OUTER JOIN WO_BreakerRail ON indRailType.RailCode = WO_BreakerRail.RailCode
WHERE (WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL)
What you want is to filter your WO_BreakerRail
to the desired date before LEFT JOINing it to indRailType
. If you just add the WHERE statement, it is done the other way around, which results in the problem you described.
The solutions provided so far should work (move the condition into the LEFT JOIN), but I'd like to suggest an alternative: You can use a subquery to specify the order in which things should be done:
SELECT R.ID, indRailType.RailType, R.CreatedPieces, R.OutsideSource, R.Charged, R.Rejected, R.RejectedToCrop
FROM indRailType LEFT OUTER JOIN
(SELECT * FROM WO_BreakerRail WHERE Date = @Date) R
ON indRailType.RailCode = R.RailCode
(Untested, but as far as I know, SQL Server CE supports subqueries.)
or you can add it to the WHERE
:
SELECT WO_BreakerRail.ID, indRailType.RailType,
WO_BreakerRail.CreatedPieces,
WO_BreakerRail.OutsideSource, WO_BreakerRail.Charged,
WO_BreakerRail.Rejected, WO_BreakerRail.RejectedToCrop
FROM indRailType, WO_BreakerRailCode
WHERE indRailType.RailCode = WO_BreakerRail.RailCode(+)
AND WO_BreakerRail.Date (+) =@Date
精彩评论