3 Tables: Device
, SoftwareRevision
, Message
. All data entered is handed by PHP scripts on an Apache server.
A device can have one software revision. A software revision can have many devices. A device can have many messages. A message can have one device.
Something like above.
The issue is, the SoftwareRevision
changes how the message is used in the front end application. This means that when the software is updated on the device, we need older messages to retain the information that they were received from a different software revision.
The TL;DR here is that the fully normalized way I see of doing this becomes a real pain. I've got about 5 of these situations in my current project and 3 of them are nested inside of each other.
I see three ways of doing this:
The first is the above fully normalized way. In order to find out how to use the message on the front end application, one must find the latest entry into Device_SoftwareRevision_Records
that is before the datetime
of the given message. This gets really fiddly when you have a more complex database and application. Just to get the current SoftwareRevision_ID
for a device you have to use a MAX GROUP BY type statement (I've ended up having to use views to simplify).
The second is to directly link the Message to the SoftwareVersion
. This means you don't have to go through the whole MAX
GROUP BY
WHERE
blah blah. The SoftwareVersion_ID
is retrieved by a PHP script and then the message is entered. Of course, this is denormalized so now there is potential for duplicate data.
Aaaand heres our fully denormalized version. The Software_Revision_Records
table is purely for bookkeeping purposes. Easy to use for the front-end application but a pain to update at the back-end. The back-end updating can actually be streamlined with triggers for entering into the Software_Revision_Records
table so the only thing that can really go wrong is the message gets the wrong software revision when it is entered.
Is there a better way of doing this that I have missed? Is it such a sin to denormalize the database in this situation? Will my decision here cause the business to erupt into flames (probably not)?
答案 0 :(得分:1)
如果消息与该特定设备的软件版本相关联,那么在数据模型中反映该关系可能更有意义。即从消息到Device_SoftwareRevision_Records而不是从消息到设备有一个外键。你仍然间接地建立了从消息到设备的关系,它已经被标准化了,并且没有弄乱日期试图弄清楚在给定的软件修订版本到位时创建了哪些消息。
如果您确实需要日期,也可能值得考虑同时拥有开始和停止日期,并填写任何空日期,例如9999-12-31(表示记录尚未结束) )。您无需max
即可轻松找到最新记录。如果你需要将它与其他日期进行比较,它也会使查询表变得容易得多 - 你可以在一条记录上做一个介于两者之间。在这个例子中,您只需查看:
where Message.TimeStamp between Device_SoftwareRevision_Records.StartDate and Device_SoftwareRevision_Records.EndDate
尽管如此,我仍然 - 如果可能的话 - 更改模型以将消息与正确的表相关联,而不是依赖于日期。如果任何新的需要学习结构,并且可能表现更好,那么能够进行简单连接将更快,更方便,更明显。