通常需要在交叉时存储多对多SQL关系的正确方法吗?

时间:2016-12-26 12:26:09

标签: mysql sql many-to-many

我有越来越多的机器列表,每台机器都连接到不同类型的设备,可以做不同的事情,我试图为此建立某种排队系统。到目前为止,我的第一个想法是使用存储可用机器的数据库表machines,从中我可以根据指定的功能选择所需的机器。所以表格看起来像这样:

machineId machineName status equipment1 equipment2 network1 network2 1 Test FREE 0 1 1 0

代码将包含参数列表,并执行搜索所有参数的代码。例如,执行SELECT * FROM Machines WHERE equipment2=1 AND network1=1 AND network2=0 AND status LIKE 'FREE'

这在理论上有效,但有两个我想避免的问题:

  1. 在添加新列时,需要在代码中定义每个字段
  2. 某些字段是互斥的。 IE我不希望连接到网络2的计算机在某些情况下运行某些测试,而某些设备会阻止机器执行某些基本功能(即使是那些不需要和设备的功能),所以我必须在代码中添加一个特定的排除项。例如。上面AND network2=0
  3. 我的下一个想法是使用连接表。所以表格是:

    Machines: machineId machineName status

    Equipments: equipemntId equipmentName exclusive

    然后我会有一个联结表

    MachinesEquipments: machineId equipmentId

    但是如果我想要一台拥有equipment2并且可以访问network1的机器,但无法访问network2(因为它标记为独占) ,也是FREE,对我来说,知道如何做到这一点太复杂了,或者即使它是正确的方式......

    对于那么多对多,这是正确的方法吗?我错过了哪些SQL文件?

1 个答案:

答案 0 :(得分:1)

你的第二个标准化版本是正确的方法。您可以使用having子句(也许还带有where子句)来解析您的查询。对于您的示例,查询是这样的:

select m.machineid
from machines m join
     machinesequipment me
     on me.machineid = m.machineid join
     equipment e
     on me.equipmentid = e.equipementid
where m.status = 'free'
group by m.machineid
having sum(e.equipmentname = 'equipment1') > 0 and   -- has "equipment1
       sum(e.equipmentname = 'equipment2') = 0;      -- does not have "equipment2"

我不知道network如何存储在此模型中,但包含它可能只是对此查询的一个简单调整。

对于网络,您可以添加其他子句,例如:

sum(e.equipmentname = 'network1') > 0

处理网络。