Рекомендуемый подход к объединению двух таблиц - PullRequest
1 голос
/ 28 сентября 2010

У меня есть схема базы данных, подобная этой:

[Patients]                    [Referrals]
     |                             |
[PatientInsuranceCarriers]    [ReferralInsuranceCarriers]
                        \        /
                    [InsuranceCarriers]

PatientInsuranceCarriers и ReferralInsuranceCarriers идентичны, за исключением того, что они ссылаются либо на пациентов, либо на рефералов. Я хотел бы объединить эти две таблицы, чтобы это выглядело так:

[Patients]      [Referrals]
       \           /
  [PatientInsuranceCarriers]
              |
      [InsuranceCarriers]

У меня есть два варианта здесь

  • либо создайте два новых столбца - ID_PatientOrReferral + IsPatient (подскажет, на какую таблицу ссылаться)
  • или создайте два разных столбца - ID_Patient и ID_Referral, оба обнуляемые.

Как правило, я стараюсь избегать пустых столбцов, потому что считаю их плохой практикой (имеется в виду, что если вы можете жить без нулей, тогда вам действительно не нужен столбец с пустыми значениями), и с ними труднее работать в коде (например, LINQ to SQL).

Однако я не уверен, что первый вариант будет хорошей идеей. Я видел, что на ID_PatientOrReferral можно создать два FK (один для пациентов и один для рефералов), хотя я не могу установить какое-либо поведение обновления / удаления по понятным причинам, я не знаю, работает ли проверка ограничений на вставку, Кстати, похоже, что ФК существуют только для того, чтобы отметить, что существуют отношения. Кроме того, я не могу создавать какие-либо внешние ключи, а вместо этого добавить отношения в DBML вручную.

Какой из подходов лучше и почему?

Ответы [ 2 ]

0 голосов
/ 28 сентября 2010

Чтобы расширить мой несколько краткий комментарий:

Я хотел бы объединить эти две таблицы

Я считаю, что это будет плохой идеей. На данный момент у вас есть две таблицы с хорошими понятными предикатами отношения (вкратце, что это означает для того, чтобы существовала запись в таблице) - и, самое главное, эти предикаты отношения разные для двух таблиц:

  • В PatientInsuranceCarriers <=> существует запись, которая Patient связана с этим Insurance Carrier

  • В ReferralInsuranceCarriers <=> существует запись, которая Referral связана с этим Insurance Carrier

Конечно, они похожи, но они не одинаковы. Теперь рассмотрим, каков будет предикат отношения объединенной таблицы:

  • Запись существует в ReferralAndPatientInsuranceCarriers <=> {(IsPatient - это true и Patient с идентификатором ID_PatientOrReferral) или альтернативно (IsPatient - это false и Referral с идентификатором ID_PatientOrReferral)} связан с этим Insurance Carrier

или если вы сделаете это с NULL s

  • Запись существует в ReferralAndPatientInsuranceCarriers <=> {(ID_Patient не NULL и Patient с идентификатором ID_Patient) или, альтернативно (ID_Referral не NULL и Referral с идентификатором ID_Referral)} связан с этим Insurance Carrier

Теперь я не из тех, кто автоматически предполагает, что более сложные отношения с педикатами обязательно хуже; но я вполне уверен, что любой из двух вышеперечисленных хуже, чем те, которые они заменят.


Для решения ваших проблем:

теперь у нас есть две сущности LINQ to SQL, отдельные контроллеры и представления для каждого

В целом я бы согласился с уменьшением дублирования; однако только дублирование одних и тех же вещей! Здесь, разве это не тот случай, когда все вышеперечисленное по сути является «образцом», а их конструкцию и обслуживание можно делегировать подходящим инструментам разработки?

и должны объединять их при подготовке данных для отчетов

Если бы вы создали VIEW, содержащий UNION, для целей отчетности, вы сохранили бы простоту фактических данных и все еще имели бы возможность составлять отчеты в комбинированном списке; Например (предположения об именах столбцов и т. д.):

CREATE VIEW InterestingInsuranceCarriers
AS
SELECT 
    IC.Name InsuranceCarrierName
    , P.Name CounterpartyName
    , 'Patient' CounterpartyType
FROM InsuranceCarriers IC
    INNER JOIN PatientInsuranceCarriers PIC ON IC.ID = PIC.InsuranceCarrierID
    INNER JOIN Patient P ON PIC.PatientId = P.ID
UNION
SELECT 
    IC.Name InsuranceCarrierName
    , R.Name CounterpartyName
    , 'Referral' CounterpartyType
FROM InsuranceCarriers IC
    INNER JOIN ReferralInsuranceCarriers RIC ON IC.ID = RIC.InsuranceCarrierID
    INNER JOIN Referral R ON PIC.ReferralId = R.ID
0 голосов
/ 28 сентября 2010

Копирование моего ответа из этого вопроса

Если вам действительно нужно A_or_B_ID в TableZ, у вас есть два аналогичных варианта:

1) Добавить nullable A_IDи B_ID столбцы таблицы z, сделать A_or_B_ID вычисляемый столбец, используя ISNULL для этих двух столбцов, и добавить ограничение CHECK, чтобы только один из A_ID или B_ID не был нулевым

2) Добавьте столбец TableName в таблицу z, ограничиваясь содержанием A или B. Теперь создайте A_ID и B_ID в качестве вычисляемых столбцов, которые становятся ненулевыми, когда их соответствующая таблица названа (используя выражение CASE).Сделайте так, чтобы они тоже сохранялись

В обоих случаях у вас теперь есть столбцы A_ID и B_ID, которые могут иметь соответствующие внешние ключи для базовых таблиц.Разница в том, какие столбцы вычисляются.Кроме того, вам не нужно TableName в варианте 2 выше, если домены столбцов с 2 идентификаторами не перекрываются - если ваше выражение регистра может определить, какой домен A_or_B_ID попадает в

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...