Условное соединение SQL Server на основе значений столбца
Я работаю над довольно сложным аспектом базы данных Equipment/Asset в SQL Server и хотел бы попросить о помощи. Я попытаюсь сосредоточиться на одной проблеме здесь, а затем задать отдельный вопрос для другой проблемы.
У меня есть таблица для оборудования под названием tblEquipment
и таблица необходимых действий, которые необходимо выполнить для коллекций оборудования (tblActionsRequired
), для этого вопроса соответствующие поля:
-
tblEquipment
: EquipmentID, BasedAtID, AreaID
-
tblRequiredActions
: AllSites (bit), BasedAtID, AreaID
Итак, идея с tblRequiredActions
заключается в том, что вы бы сказали, что все оборудование на сайте Site A необходимо проверять так часто. Районы - это конкретные комнаты или офисы и т.д. На сайте. Таким образом, если AllSites истинно, действие распространяется на все оборудование всей компании, если оно ложно, тогда требуется BaseAtID (для сайта), AreaID является необязательным, если вы хотите еще больше сузить его.
Итак, теперь проблема заключается в том, чтобы извлечь, какие действия должны применяться к тому, какое оборудование основывается на этих трех полях.
Теперь у меня есть то, что, как я думаю, может работать, но я изо всех сил пытаюсь проверить мои результаты, так как есть другие факторы, которые меня тоже путают, поэтому я бы очень признателен за подтверждение или руководство, если я полностью ошибаюсь! Я не хочу идти по пути хранимых процедур и блоков или союзов, поскольку есть несколько других измерений, которые должны быть покрыты схожим принципом, и я в конечном итоге напишу массово сложную процедуру, которая станет кошмаром для поддержания, Спасибо!!
SELECT
dbo.tblActionsRequired.ActionID, dbo.tblEquipment.EquipmentID
FROM
dbo.tblEquipment
INNER JOIN
dbo.tblActionsRequired ON dbo.tblActionsRequired.AllSites = 'True'
OR dbo.tblEquipment.AreaID IS NULL
AND dbo.tblEquipment.BasedAtID = dbo.tblActionsRequired.BasedAtID
OR dbo.tblEquipment.AreaID IS NOT NULL
AND dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID
Ответы
Ответ 1
Существующий запрос выглядит довольно хорошо для меня, хотя его можно немного упростить:
SELECT dbo.tblActionsRequired.ActionID, dbo.tblEquipment.EquipmentID
FROM dbo.tblEquipment
JOIN dbo.tblActionsRequired
ON dbo.tblActionsRequired.AllSites = 'True' OR
(dbo.tblEquipment.AreaID IS NULL AND
dbo.tblEquipment.BasedAtID = dbo.tblActionsRequired.BasedAtID) OR
dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID
- так как если оба a.AreaID и e.AreaID равны нулю, то условие dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID
не оценивается как истина.
(Скобки не требуются строго, но были включены для ясности.)
Ответ 2
Похож на меня; Ваша логика и подход выглядят здорово.
Хотя комбинации AND/OR могут быть открыты для неправильной интерпретации... Возможно, рассмотрите группировку ваших выражений AND в круглых скобках (я знаю, что это избыточно, но это разъясняет ваши намерения). И в соответствии с недавним ответом @MarkBannister это может показать возможность факторизации булевой алгебры: -)
Я лично перенес любую "фильтрацию" из предложения внутреннего соединения ON в предложение WHERE, оставив только выражения, относящиеся к самому соединению, в случае, когда только одно соединение и эти фильтры изолированы от сама логика соединения. Но здесь это не так.
Индексы, вероятно, повлияют на этот способ или другой... Проверьте план выполнения, чтобы узнать, можно ли добавить некоторые из своих FK или текстового поля.
Ответ 3
Я не думаю, что вам нужно не null
Если AreaID имеет значение null, то dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID будет оценивать значение null
SELECT
dbo.tblActionsRequired.ActionID, dbo.tblEquipment.EquipmentID
FROM
dbo.tblEquipment
INNER JOIN
dbo.tblActionsRequired
ON dbo.tblActionsRequired.AllSites = 'True'
OR dbo.tblEquipment.AreaID IS NULL
AND dbo.tblEquipment.BasedAtID = dbo.tblActionsRequired.BasedAtID
OR dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID