ВЕРНУТЬСЯ ВНУТРЕННЕЙ РАБОТЫ с предложением WHERE
У меня две таблицы. indRailType
содержит список имен в паре с идентификационным значением, которое я использую в других таблицах, чтобы указать тип рельса. WO_BreakerRail
содержит столбец даты и столбец рельсового кода, соответствующий тому же коду в indRailType
и некоторым другим данным. Для каждой операции на каждом типе рельса для каждой даты есть строка в WO_BreakerRail
. Таким образом, у меня могло бы быть 3 строки, датированные 3/19/2010
, каждая строка указывает другой код рельса и что произошло.
Когда я использую следующий LEFT OUTER JOIN
, я получаю таблицу со всеми типами рельсов с нулями в строках, где ничего не произошло на 19-м. Теперь это работает, потому что у меня есть только одна дата, представленная в моей таблице WO_BreakerRail
прямо сейчас, 19-го. Когда я добавлю несколько строк с разными датами, все будет схоже.
Это мой оператор SQL, который прямо сейчас дает мне именно те результаты, которые я хочу:
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
, я теряю все строки в JOIN
, которые ничего не произошло. Я не хочу этого. От чтения это звучит как FULL OUTER JOIN
- это то, что я хочу, но SQL Server Compact Edition не поддерживает FULL OUTER JOIN
s. Есть ли способ обойти это, или я ищу что-то еще полностью?
Ответы
Ответ 1
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
Таким образом, добавив AND WO_BreakerRail.Date = @Date
к соединению
Ответ 2
Условие предиката должно быть в предложении On
для соединения, а не в предложении where. Как работают внешние соединения, после анализа условий соединения все строки из "внешней стороны", которые не соответствуют внутренней стороне, добавляются обратно... Но все это происходит до того, как предложение where будет обработано. Поэтому, если предикат where where отключает атрибут с внешней стороны внешнего соединения, все эти строки будут удалены снова... (Все они равны нулю). Вместо этого поставьте предикат в условие соединения, затем он будет оценен до того, как недостающие строки будут добавлены обратно в...
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
Ответ 3
Вы можете использовать это предложение where:
WHERE WO_BreakerRail.Date = @Date OR WO_BreakerRail.Date IS NULL
Ответ 4
добавьте WO_BreakerRail.Date = @Date
в оператор LEFT OUTER JOIN
, а не 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
или вы можете добавить его в ГДЕ:
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)
Ответ 5
или вы можете добавить его в 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 (+) [email protected]
Ответ 6
Вы хотите отфильтровать ваш WO_BreakerRail
до нужной даты, прежде чем LEFT JOINING его на indRailType
. Если вы просто добавляете инструкцию WHERE, это делается наоборот, что приводит к описанной проблеме.
Предлагаемые решения должны работать (переместите условие в LEFT JOIN), но я хотел бы предложить альтернативу: вы можете использовать подзапрос, чтобы указать порядок, в котором должны быть выполнены:
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, но, насколько я знаю, SQL Server CE поддерживает подзапросы.)