SQL 设计、连接类型和子类型
我正在制作一个交通记录前端,它允许显示有关财产上特定车辆的信息以及搜索特定车辆,但我不确定继续进行数据库设计的最佳方法。我想要做的是能够根据车辆类型和该车辆的功能/子类型快速调出所有车辆记录。我不知道如何最好地从我的单一车辆记录中参考多个子类型/功能。这是一个简化的示例:
我有一个车辆表:
VehicleID, LicensePlate, TypeID, SubTypeIDs
1 , 111111 , 2 , ;2;;3;
一个车辆类型表:
TypeID, Type
1 , Car
2 , Semi
和一个车辆子类型表: Vehicles.Subtype
SubTypeID, TypeID, SubType
1 , 1 , Coupe
2 , 2 , Flat Bed
2 , 2 , Sleeper
字段是一个 varchar,其中我当前只是删除引用 VehicleSubTypes.SubTypeID 的子类型。 .. 这个想法是,从前端,在列出可用选项时挑选出每个 SubTypeID,并查找引用的 SubType 字符串(即“Coupe”)以显示给用户,或者更重要的是,当搜索带有卧铺和平床的半挂车时,要包含子类型“%;2;%”和“%;3;%”子句,以仅获取包含这两种功能的车辆。我现在只是在考虑这个解决方案,因为我已经休假一年了,我的大脑已经停止工作了:)我确信这是糟糕的数据库设计!但对于我的生活,我想不出更合适的方法,而且我所有的谷歌搜索努力不断出现根本不适用的子类型示例,或者我错过了与(即具有多组联系人的人)的相似之处信息..人员显然应该是一个表,联系信息显然应该是另一个表,他们通过 personID 链接,等等)
编辑/结论:
感谢 Bort 扰乱了我的记忆并指出我指向链接表。我现在添加了一个表 Link_VehicleToSubTypes:
linkID, VehicleID, SubTypeID
1 , 1 , 2
2 , 2 , 10 //10 = Cargo (Semi)
3 , 2 , 15 //15 = No Sleeper
此外,我还创建了以下存储过程来返回与我传递给它的所有参数(最多 10 个)匹配的车辆的 VehicleID - 这样我以后就可以加入这个信息与搜索我的车辆表的结果相比较,其中包括特定于车辆的信息,例如 Vehicle.Color,因此我可以过滤最终结果集:
ALTER PROCEDURE dbo.ReturnVehicleIDsMatchingSubTypes
(
@SubType1 int = NULL,
@SubType2 int = NULL,
@SubType3 int = NULL,
@SubType4 int = NULL,
@SubType5 int = NULL,
@SubType6 int = NULL,
@SubType7 int = NULL,
@SubType8 int = NULL,
@SubType9 int = NULL,
@SubType10 int = NULL
)
AS
DECLARE @intNumberSubTypesToMatch int SET @intNumberSubTypesToMatch =
(SELECT COUNT(@SubType1)
+ COUNT(@SubType2)
+ COUNT(@SubType3)
+ COUNT(@SubType4)
+ COUNT(@SubType5)
+ COUNT(@SubType6)
+ COUNT(@SubType7)
+ COUNT(@SubType8)
+ COUNT(@SubType9)
+ COUNT(@SubType10))
SELECT VehicleID
FROM Link_VehicleToSubTypes
WHERE
SubTypeID IN (@SubType1, @SubType2, @SubType3, @SubType4, @SubType5, @SubType6, @SubType7, @SubType8, @SubType9, @SubType10)
GROUP BY VehicleID
HAVING (COUNT(*) = @intNumberSubTypesToMatch)
RETURN
我已经对此进行了测试,并且运行良好。我的存储过程的实现可能有点奇怪(我以前从未需要计算非空参数,这个方法就是我想到的),但它有效。 Bort - 当我有足够的积分时我会给你+1!非常感谢您的帮助!
I'm making a traffic logging front end which allows displaying information on a specific vehicle on property as well as searching for a specific vehicle, but am unsure of the best way to proceed with my database design. What I want to do is be able to quickly pull up all vehicle records based on the type of vehicle and features/subtypes of that vehicle. I don't know how best to make reference from my single vehicle record to multiple subtypes/features. Here's a simplified example:
I have a table for Vehicles:
VehicleID, LicensePlate, TypeID, SubTypeIDs
1 , 111111 , 2 , ;2;;3;
A table for VehicleTypes:
TypeID, Type
1 , Car
2 , Semi
And a table for VehicleSubTypes:
SubTypeID, TypeID, SubType
1 , 1 , Coupe
2 , 2 , Flat Bed
2 , 2 , Sleeper
The Vehicles.Subtype field is a varchar, in which I'm currently just deleniating out the Subtypes which reference to VehicleSubTypes.SubTypeID... The idea is to, from the front end, pick out each SubTypeID when listing available options and look up the referenced SubType string (ie, "Coupe") to display to the user, or more importantly when searching for a Semi with a sleeper and a flat bed to include a SubTypes LIKE '%;2;%' AND '%;3;%' clause to get only vehicles that include both features. I'm only thinking of this solution though right now because I've been on vacation for a year and my brain is stalling out on me :) I feel certain this is awful DB design! But for the life of me I can't think of a more proper way, and all my googling efforts keep turning up subtype examples that simply don't apply or I'm missing the similarity with (ie, people with multiple sets of contact information.. people should obviously be one table, contact info should obviously be another, they link by personID, etc etc)
EDIT/Conclusion:
Thanks to Bort for jarring my memory and pointing me toward a link table. I've now added a table, Link_VehicleToSubTypes:
linkID, VehicleID, SubTypeID
1 , 1 , 2
2 , 2 , 10 //10 = Cargo (Semi)
3 , 2 , 15 //15 = No Sleeper
In addition, I've created the following stored procedure to return VehicleIDs for vehicles that match all parameters (up to 10) that I've passed to it - this way I can later join this info against results from searching my Vehicles table which includes vehicle-specific info such as Vehicle.Color, and thus I can filter a final result set:
ALTER PROCEDURE dbo.ReturnVehicleIDsMatchingSubTypes
(
@SubType1 int = NULL,
@SubType2 int = NULL,
@SubType3 int = NULL,
@SubType4 int = NULL,
@SubType5 int = NULL,
@SubType6 int = NULL,
@SubType7 int = NULL,
@SubType8 int = NULL,
@SubType9 int = NULL,
@SubType10 int = NULL
)
AS
DECLARE @intNumberSubTypesToMatch int SET @intNumberSubTypesToMatch =
(SELECT COUNT(@SubType1)
+ COUNT(@SubType2)
+ COUNT(@SubType3)
+ COUNT(@SubType4)
+ COUNT(@SubType5)
+ COUNT(@SubType6)
+ COUNT(@SubType7)
+ COUNT(@SubType8)
+ COUNT(@SubType9)
+ COUNT(@SubType10))
SELECT VehicleID
FROM Link_VehicleToSubTypes
WHERE
SubTypeID IN (@SubType1, @SubType2, @SubType3, @SubType4, @SubType5, @SubType6, @SubType7, @SubType8, @SubType9, @SubType10)
GROUP BY VehicleID
HAVING (COUNT(*) = @intNumberSubTypesToMatch)
RETURN
I've tested this out and it's working well. My implementation of the stored procedure may be a bit wonky (I've never had to count non null parameters before, this method is all that came to mind), but it works. Bort - I'll +1 you when I have enough points to do so! Your help is greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于像使用子类型一样将多个值存储在单个列中几乎总是一个坏主意(需要执行
LIKE '%;2;%' AND LIKE '%;3;%'
是一个巨大的任务红旗),如果我正确理解了您的要求,这看起来像是多对多关系,通常涉及一个交叉表来链接两个实体,在本例中为车辆和子类型。如果您从车辆表中删除了 SubTypeID,并创建了一个链接表 Vehicle_Subtypes,
那么您将能够编写查询来获取给定车辆的适当子类型,例如
可能需要更多逻辑来解释 TypeID,但这似乎是正确的设计。
编辑:我收回一切。误解了从子类型到车辆的部分,把它放在我的脑海里。反之则更困难,查找满足可变数量条件的记录可能会很棘手。给定相同的链接表(假设您对生成的 SQL 有很多控制权),您可以编写有点黑客的查询
您必须确保
COUNT(*) =
选择的子类型数量,这样车辆就拥有了所有这些。不过,感觉应该还有更好的办法,我会继续思考。Since storing multiple values in a single column like you are with SubTypes is almost always a bad idea (Needing to do
LIKE '%;2;%' AND LIKE '%;3;%'
is a huge red flag), if I've understood your requirements correctly this looks like a many to many relationship, which usually involves a cross table to link the two entities, in this case Vehicles and Subtypes.If you removed SubTypeIDs from your Vehicle table, and created a link table Vehicle_Subtypes
You would then be able to write queries to get the appropriate SubTypes for a given vehicle, something like
May need more logic in there to account for TypeID but this seems like the right design.
EDIT: I take it all back. Misunderstood the part about going from SubTypes to Vehicles, had it backwards in my head. Going the other way is more difficult, finding records that meet a variable number of conditions can be tricky. Given the same link table, (assuming you have a lot of control over the SQL that gets generated) you could write the somewhat hackish query
You would have to ensure
COUNT(*) =
number of subtypes selected, this way the vehicle has all of them. Still, it feels like there should be a better way, I'll keep thinking on it.我会做这样的事情:
通过这个设计和一些SQL,你可以获得你想要的数据。
I'd do something like this:
With this design and some SQL you can get the data you want.