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 JOINs. 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
加载中,请稍侯......
精彩评论