SQL设计,连接类型和子类型

时间:2012-02-17 02:12:51

标签: sql one-to-many subtype

我正在制作一个流量记录前端,它允许在属性上显示特定车辆的信息以及搜索特定车辆,但我不确定最佳方式来继续我的数据库设计。我想要做的是能够根据车辆的类型和该车辆的特征/子类型快速提取所有车辆记录。我不知道如何最好地从我的单一车辆记录中引用多个子类型/功能。这是一个简化的例子:

我有一张车辆表:

VehicleID, LicensePlate, TypeID, SubTypeIDs
1        ,   111111    ,   2   ,   ;2;;3;

VehicleTypes表:

TypeID, Type
  1   ,  Car
  2   ,  Semi

还有一个VehicleSubTypes表:

SubTypeID,  TypeID,   SubType
1        ,   1    ,   Coupe
2        ,   2    ,   Flat Bed
2        ,   2    ,   Sleeper

Vehicles.Subtype字段是一个varchar,我目前正在删除引用VehicleSubTypes.SubTypeID的Subtypes ...想法是从前端选择列出可用选项时的每个SubTypeID并查找引用的SubType字符串(即“Coupe”)以显示给用户,或者更重要的是在搜索具有睡眠者和平床的Semi时包含子类型LIKE'%; 2;%'AND'% ; 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

我已经对此进行了测试,但效果很好。我对存储过程的实现可能有点不稳定(我以前从来没有计算过非null参数,这种方法就是我想到的),但它确实有效。 Bort - 当我有足够的积分时,我会给你+1!非常感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

因为像Subtypes一样在单个列中存储多个值几乎总是一个坏主意(需要做LIKE '%;2;%' AND LIKE '%;3;%'是一个巨大的红旗),如果我正确理解你的要求,这看起来像一个多对多的关系,通常涉及一个交叉表来链接这两个实体,在这种情况下是车辆和子类型。

如果您从Vehicle表中删除了SubTypeID,并创建了一个链接表Vehicle_Subtypes

VehicleID   SubTypeID
1           2
1           3

然后,您就可以编写查询以获取给定车辆的相应子类型,例如

SELECT S.SubType FROM SubTypes S
    INNER JOIN Vehicle_Subtypes X ON X.SubTypeID = S.SubTypeID
WHERE X.VehicleID = @VehicleId

可能需要更多逻辑来解释TypeID,但这似乎是正确的设计。

编辑:我把它全部收回来。误解了从子类型到车辆的部分,让它倒在了我的头脑中。走另一条路是比较困难的,找到满足不同条件的记录可能会很棘手。给定相同的链接表,(假设您对生成的SQL有很多控制权),您可以编写有点hackish查询

SELECT VehicleId FROM Vehicle_Subtypes 
WHERE SubTypeId IN (1, 2)
GROUP BY VehicleId
HAVING COUNT(*) = 2

您必须确保选择COUNT(*) =个子类型,这样车辆就拥有了所有这些子类型。不过,感觉应该有一个更好的方法,我会继续思考它。

答案 1 :(得分:0)

我会做这样的事情:

  • 包含车辆ID,LicencePlate和TypeID(FK)列的车辆表。车辆ID是PK。
  • VehicleSubTypes表,其中包含TypeID,SubTypeID和SubType列。 TypeID和SubTypeID是PK的
  • VehicleFeatures表,其中包含Vehicle ID(FK),TypeID和SubTypeID列。 TypeID和SubTypeID是FK到VehicleSubTypes。您的PK可以自动生成。

使用此设计和一些SQL,您可以获得所需的数据。