简体   繁体   English

SQL Server条件连接基于列值

[英]SQL Server conditional join based on column values

I'm working on a fairly complicated aspect to an Equipment / Asset database in SQL Server and would like to ask for some help please. 我正在为SQL Server中的设备/资产数据库做一个相当复杂的方面,并且想请求一些帮助。 I'll try and focus on one issue here and then ask a separate question for another problem. 我会尝试在这里关注一个问题,然后针对另一个问题提出单独的问题。

I have a table for equipment called tblEquipment and a table for required actions that need to be performed on collections of equipment ( tblActionsRequired ), for the sake of this question the relevant fields are: 我有一个名为tblEquipment设备表和一个表,用于需要对设备集合执行的操作( tblActionsRequired ),为了这个问题,相关字段是:

  • tblEquipment : EquipmentID, BasedAtID, AreaID tblEquipmentEquipmentID, BasedAtID, AreaID
  • tblRequiredActions : AllSites (bit), BasedAtID, AreaID tblRequiredActionsAllSites (bit), BasedAtID, AreaID

So the idea with tblRequiredActions is that you'd say all equipment at company Site A needs to be inspected every so often. 所以tblRequiredActions的想法就是你要说公司Site A的所有设备都需要经常检查。 Areas are specific rooms or offices etc. at a site. 区域是一个站点的特定房间或办公室等。 So if AllSites is true the action applies to all equipment company-wide, if it's false then BasedAtID (for the site) is required, AreaID is optional if you want to narrow it down even more. 因此,如果AllSites为true,则该操作适用于公司范围内的所有设备,如果它是假的,则需要BasedAtID(对于该站点),如果您想要将其缩小范围,则AreaID是可选的。

So now the problem to extract which actions should be applied to which equipment based on these three fields. 那么现在要解决的问题是应该根据这三个领域应用哪些设备。

What I have now is what I think might work but I'm struggling to verify my results as there are other factors confusing me as well, so would really appreciate some confirmation or guidance if I'm completely on the wrong track! 我现在所拥有的是我认为可行的,但我正在努力验证我的结果,因为还有其他因素让我感到困惑,所以如果我完全走错了路,我会非常感谢你的确认或指导! I don't want to go the route of stored procedures and if blocks or unions as there are multiple other dimensions that need to be covered with the similar principle and I'll end up writing a massively complicated procedure that will be a nightmare to maintain. 我不想走存储过程的路线,如果是块或联合,因为有许多其他维度需要用相似的原则来涵盖,我最终会编写一个大规模复杂的程序,这将是一个噩梦来维持。 Thanks!! 谢谢!!

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

The existing query looks pretty good to me, although it can be simplified slightly: 现有的查询对我来说非常好,虽然它可以略微简化:

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

- since if both a.AreaID and e.AreaID are null, then the condition dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID does not evaluate as true. - 因为如果a.AreaID和e.AreaID都为null,则条件dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID不会评估为true。

(The parentheses aren't strictly required, but were included for clarity.) (括号不是严格要求的,但为了清楚起见,包括在内。)

Looks correct to me; 对我来说是正确的; Your logic and approach look sound. 你的逻辑和方法看起来很合理。

Although the combinations of AND/OR might be open to misinterpretation... Perhaps consider grouping your AND expressions in parenthesis (I know this is redundant, but doing so clarifies your intent ). 虽然AND / OR的组合可能会被误解......也许考虑将你的AND表达式括在括号中(我知道这是多余的,但这样做可以澄清你的意图 )。 And as per @MarkBannister's recent answer, this might reveal an opportunity for Boolean algebra factorization :-) 根据@MarkBannister最近的回答,这可能会揭示布尔代数分解的机会:-)

I'd personally move any "filtering" out of the inner join's ON clause, into a WHERE clause, leaving just the expressions that relate to the join itself, in the case where there's only one join and those filters are isolated from the join logic itself. 我个人将内部连接的ON子句中的任何“过滤”移动到WHERE子句中,只留下与连接本身相关的表达式,如果只有一个连接并且这些过滤器与连接逻辑隔离本身。 But this is not the case here. 但这不是这种情况。

Indexes will probably affect this one way or the other... Check your execution plan to see if you'd benefit from adding some on your FKs or the text field. 索引可能会影响这种方式或其他方式...检查您的执行计划,看看您是否可以在FK或文本字段中添加一些内容。

I don't think you need the not null 我认为你不需要null
If AreaID is null then dbo.tblEquipment.AreaID = dbo.tblActionsRequired.AreaID will evaluate to 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM