use*_*012 2 sql sql-server join
我有一张维护要求表和相关的每月执行频率
维护
+----------+------+
| maint_id | freq |
+----------+------+
| 1 | 6 |
| 2 | 12 |
| 3 | 24 |
| 4 | 3 |
+----------+------+
Run Code Online (Sandbox Code Playgroud)
我还有一个设备表,其中包含有关其制造商、型号、设备类型和建筑物的数据。
装备
+----------+--------+--------+--------+---------+
| equip_id | mfg_id | mod_id | dev_id | bldg_id |
+----------+--------+--------+--------+---------+
| 1 | 1 | 1 | 3 | 1 |
| 2 | 1 | 2 | 3 | 1 |
| 3 | 2 | 3 | 1 | 2 |
| 4 | 2 | 3 | 1 | 3 |
+----------+--------+--------+--------+---------+
Run Code Online (Sandbox Code Playgroud)
我试图将每个维护要求与其相关设备相匹配。每项要求适用于其应用范围内的特定制造商、型号、设备、设施或这些的任意组合。我创建了一个表来管理这些关系,如下所示:
维护装备
+----------------+----------+--------+--------+--------+---------+
| maint_equip_id | maint_id | mfg_id | mod_id | dev_id | bldg_id |
+----------------+----------+--------+--------+--------+---------+
| 1 | 1 | NULL | NULL | 1 | NULL |
| 2 | 2 | 2 | NULL | NULL | 2 |
| 3 | 3 | NULL | NULL | NULL | 1 |
| 4 | 3 | NULL | NULL | NULL | 3 |
| 5 | 4 | 1 | NULL | 3 | 1 |
+----------------+----------+--------+--------+--------+---------+
Run Code Online (Sandbox Code Playgroud)
根据上表,要求 1 仅适用于设备类型为“1”的任何设备。要求 2 将适用于同时具有制造商“2”和建筑“2”的所有设备。要求 3 将适用于具有建筑物“1”或建筑物“3”的所有设备 要求 4 将适用于具有所有 mfg_id“1”和 dev_id“3”和建筑物“1”的设备。
我正在尝试编写一个查询,根据 maint_equip 中定义的关系为我提供所有设备 ID 和所有相关频率要求的列表。我遇到的问题是处理多个连接。我已经尝试过:
SELECT equip.equip_id, maint.freq
FROM equip INNER JOIN
maint_equip ON equip.mfg_id = maint_equip.mfg_id
OR equip.mod_id = maint_equip.mod_id
OR equip.dev_id = maint_equip.dev_id
OR equip.bldg_id = maint_equip.bldg_id INNER JOIN
maint ON maint_equip.maint_id = maint.maint_id
Run Code Online (Sandbox Code Playgroud)
但是使用 OR 分隔多个连接意味着它没有考虑每一行的 AND 意外事件。例如,maint_id 2 应该只适用于equip_id 3,但ids 3 和4 都被返回。如果使用 AND,则不会返回任何行,因为所有列都没有值。
是否有可能以这种方式连接表来实现这一点,或者是否有另一种方式来构建数据?
如果我做对了,当与设备相关的 IDmaint_equip为空时,这应该算作匹配。只有当它不为空时,它才必须匹配equip. 也就是说,您想检查一个 ID inmaint_equip是否为 null 或等于它的对应 from equip。
SELECT e.equip_id,
m.freq
FROM equip e
INNER JOIN maint_equip me
ON (me.mfg_id IS NULL
OR me.mfg_id = e.mfg_id)
AND (me.mod_id IS NULL
OR me.mod_id = e.mod_id)
AND (me.dev_id IS NULL
OR me.dev_id = e.dev_id)
AND (me.bldg_id IS NULL
OR me.bldg_id = e.bldg_id)
INNER JOIN maint m
ON m.maint_id = me.main_id;
Run Code Online (Sandbox Code Playgroud)