SQL Design, объединение типов и подтипов

Я создаю внешний интерфейс регистрации трафика, который позволяет отображать информацию о конкретном транспортном средстве на территории, а также искать конкретное транспортное средство, но я не уверен, наилучший способ приступить к проектированию моей базы данных. Что я хочу сделать, так это иметь возможность быстро просматривать все записи о транспортных средствах в зависимости от типа транспортного средства и характеристик/подтипов этого транспортного средства. Я не знаю, как лучше всего сделать ссылку из моей записи об одном автомобиле на несколько подтипов/функций. Вот упрощенный пример:

У меня есть таблица для транспортных средств:

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

Таблица для типов транспортных средств:

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... Идея состоит в том, чтобы из внешнего интерфейса выбрать каждый SubTypeID при перечислении доступных вариантов и найти указанная строка подтипа (т. е. «Купе») для отображения пользователю или, что более важно, при поиске полуприцепа со спальным местом и плоской платформой для включения подтипов LIKE '%;2;%' AND '%;3; %', чтобы получить только автомобили, которые включают обе функции. Я только думаю об этом решении прямо сейчас, потому что я был в отпуске в течение года, и мой мозг застопорился на мне :) Я уверен, что это ужасный дизайн БД! Но убей меня, я не могу придумать более правильного способа, и все мои усилия по гуглению продолжают находить примеры подтипов, которые просто не применимы или я упускаю сходство с (т.е. людьми с несколькими наборами контактов информация.. люди, очевидно, должны быть одной таблицей, контактная информация, очевидно, должна быть другой, они связываются по идентификатору человека и т. д. и т. д.)

EDIT/Вывод:

Спасибо Борту за то, что встряхнул мою память и указал мне на таблицу ссылок. Теперь я добавил таблицу Link_VehicleToSubTypes:

linkID, VehicleID, SubTypeID
  1   ,   1      ,    2
  2   ,   2      ,    10     //10 = Cargo (Semi)
  3   ,   2      ,    15     //15 = No Sleeper

Кроме того, я создал следующую хранимую процедуру для возврата идентификаторов транспортных средств для транспортных средств, которые соответствуют всем параметрам (до 10), которые я передал ей, таким образом, я могу позже сопоставить эту информацию с результатами поиска в моей таблице транспортных средств, которая включает информация о конкретном транспортном средстве, такая как 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

Я проверил это, и это работает хорошо. Моя реализация хранимой процедуры может быть немного неуклюжей (мне никогда раньше не приходилось считать ненулевые параметры, это все, что пришло мне в голову), но она работает. Борт — я поставлю +1, когда у меня будет достаточно очков для этого! Ваша помощь очень ценится!


person maxx233    schedule 17.02.2012    source источник
comment
+1, потому что вы уверены, что это ужасный дизайн. Действительно так (столбец SubTypeIds :)   -  person ypercubeᵀᴹ    schedule 17.02.2012
comment
См. пример транспортных средств в этой статье: Уникальный опыт! Джо Селко (он подробно рассказывает об этом в нескольких темах групп новостей, например, здесь ).   -  person onedaywhen    schedule 17.02.2012


Ответы (2)


Поскольку хранение нескольких значений в одном столбце, как у вас с подтипами, почти всегда является плохой идеей (необходимость делать LIKE '%;2;%' AND LIKE '%;3;%' - это огромный красный флаг), если я правильно понял ваши требования, это выглядит как отношение многие ко многим, что обычно включает перекрестную таблицу для связи двух объектов, в данном случае транспортных средств и подтипов.

Если вы удалили SubTypeID из таблицы Vehicle и создали таблицу ссылок 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), вы можете написать несколько хакерский запрос

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

Вы должны убедиться, что выбрано COUNT(*) = количество подтипов, таким образом, транспортное средство будет иметь их все. Тем не менее, похоже, что должен быть лучший способ, я буду думать об этом.

person Bort    schedule 17.02.2012
comment
Это определенно на правильном пути. Таблица ссылок была важной концепцией, которую мой мозг, кажется, потерял за год бездействия;) Сейчас я работаю над изменениями и соответствующими тестами для этого, я уверен, что это правильный дизайн. Мне просто нужно собрать реализацию, лол - person maxx233; 17.02.2012
comment
Хм... Ну, теперь я со всем этим разобрался, но, поскольку я новичок, это не позволит мне дать ответ "слишком быстро"... Но у меня есть хороший вывод, готовый подняться. еще через 3 часа;) Будет включен SP, который я придумал, чтобы упростить ввод значений и ожидание правильного результата. Борт. Я обязательно поставлю вам +1, как только это позволит мне, ваша помощь была решающей. - person maxx233; 17.02.2012

Я бы сделал что-то вроде этого:

  • Таблица транспортных средств со столбцами идентификатор транспортного средства, номерной знак и идентификатор типа (FK). Идентификационный номер автомобиля - ПК.
  • Таблица VehicleSubTypes со столбцами TypeID, SubTypeID и SubType. TypeID и SubTypeID являются PK
  • Таблица VehicleFeatures со столбцами Vehicle ID (FK), TypeID и SubTypeID. TypeID и SubTypeID являются FK для VehicleSubTypes. Ваш ПК может быть сгенерирован автоматически.

С этим дизайном и некоторыми SQL вы можете получить данные, которые вы хотите.

person Carlos Gavidia-Calderon    schedule 17.02.2012