Условное соединение 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