基于列值的SQL Server条件联接

基于列值的SQL Server条件联接,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在处理SQL Server中设备/资产数据库的一个相当复杂的方面,希望获得一些帮助。我会在这里试着把注意力集中在一个问题上,然后就另一个问题问另一个问题 我有一个名为tblEquipment的设备表和一个需要在设备集合上执行的所需操作表(tblactionrequired),针对这个问题,相关字段包括: tblEquipment:EquipmentID、BasedAtID、AreaID tblRequiredActions:所有站点(位)、BasedAtID、AreaID 因此,tblR

我正在处理SQL Server中设备/资产数据库的一个相当复杂的方面,希望获得一些帮助。我会在这里试着把注意力集中在一个问题上,然后就另一个问题问另一个问题

我有一个名为
tblEquipment
的设备表和一个需要在设备集合上执行的所需操作表(
tblactionrequired
),针对这个问题,相关字段包括:

  • tblEquipment
    EquipmentID、BasedAtID、AreaID
  • tblRequiredActions
    所有站点(位)、BasedAtID、AreaID
因此,
tblRequiredActions
的想法是,您可以说公司现场A的所有设备都需要经常检查。区域是现场的特定房间或办公室等。因此,如果AllSites为true,则该操作适用于公司范围内的所有设备,如果为false,则需要BasedAtID(用于站点),如果希望进一步缩小范围,则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

在我看来是正确的;你的逻辑和方法看起来很合理

虽然和/或的组合可能会被误解。。。也许考虑将括号中的表达式和表达式分组(我知道这是多余的,但这样做可以澄清你的意图)。根据@MarkBannister最近的回答,这可能揭示了布尔代数因式分解的机会:-)

我个人会将任何“过滤”从内部连接的ON子句移到WHERE子句中,只留下与连接本身相关的表达式,如果只有一个连接,并且这些过滤器与连接逻辑本身隔离。但事实并非如此


索引可能会以这样或那样的方式影响这一点。。。检查您的执行计划,看看在FKs或文本字段中添加一些内容是否有好处。

我认为您不需要NOTNULL
如果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

现有查询在我看来相当不错,不过可以稍微简化一下:

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.tblactionrequired.AreaID
不会计算为真


(括号不是严格要求的,但为了清楚起见被包括在内。)

超级挑剔:如果AreaID为null,那么dbo.tblEquipment.AreaID=dbo.tblActionsRequired.AreaID将计算为null,而不是false-在这里,这没有什么区别,但是如果添加了
not
,则null表达式仍将计算为null,而一个假表达式的计算结果将是真的。@MarkBannister OK将其更改为null+1,要求正确。。。有足够的细节来自信地回答你的问题。但请确保按照marc_的编辑要求进行干净的格式设置。。。如果人们能很容易地读懂你想要表达的内容,你会对你产生更大的兴趣。好的,谢谢@sepsterThank,非常感谢Mark,这是有道理的,至少我现在知道步骤1是可以的,必须创建一个新问题,下一个复杂的问题:)非常感谢!你好,马克·班尼斯特,我想知道你是否介意看看我的新问题?非常感谢。谢谢你,塞普斯特,我一定会检查索引,一旦我满意的充分query@ebooyens我的荣幸!祝你好运考虑将括号内的表达式和表达式分组(我知道这是多余的)…你确定吗?直到现在我才尝试过(现在我仍然没有,几分钟后我会尝试),但是括号在
WHERE
子句中是至关重要的,所以我无法想象
JOIN
与said
WHERE
…@AcePL是的,我确信。AND算子比OR算子具有更高的算子频度。在WHERE和UNION表达式中(以及在大多数/所有实现经典布尔逻辑的编程语言中)。