Я рекомендую вам пойти на ваш вариант 2. Я вполне уверен, что Крис Дэйн тоже хотел бы, потому что по сути то, что вы делаете, полностью нормализуется до 6NF , максимально возможной нормальной формы, которая Дата была несет совместную ответственность за введение .
Я рекомендую документ Дарвена об обработке недостающей информации.
Так как НАРУЖНЫЕ СОЕДИНЕНИЯ не будут разрешены (потому что они вводят NULL
в набор результатов), все необходимые данные больше не могли
получать с помощью одного запроса, как и раньше.
… это не тот случай, но я согласен с тем, что проблема внешнего объединения явно не упоминается в статье Дарвена; это было единственное, что оставило меня желать. Четкий ответ можно найти в другой книге Дейта ...
Во-первых, обратите внимание, что Date и собственный действительно реляционный язык Дарвена Tutorial D имеет только один тип соединения, являющийся естественным соединением. Обоснование состоит в том, что на самом деле нужен только один тип соединения.
Книга данных, на которую я ссылался, является превосходной SQL и реляционная теория: как написать точный код SQL :
4.6: Замечание по внешнему объединению: «Говоря языком, [внешнее объединение]
вид брака с дробовиком: он превращает столы в своего рода союз - да, я
означает объединение, а не объединение, даже если рассматриваемые таблицы не
соответствовать обычным требованиям для союза ... Это делает это, в
эффект, добавив одну или обе таблицы с нулями перед выполнением
союз, тем самым заставляя их соответствовать этим обычным требованиям
в конце концов. Но нет никаких причин, почему это заполнение не должно быть сделано
с правильными значениями вместо нулей
Используя ваш пример и значение по умолчанию '1900-01-01' в качестве 'padding', альтернатива внешнему объединению может выглядеть так:
SELECT p.PersonID, p.Name, b.DateOfBirth
FROM Person AS p
INNER JOIN BirthDate AS b
ON p.PersonID = b.PersonID
UNION
SELECT p.PersonID, p.Name, '1900-01-01' AS DateOfBirth
FROM Person AS p
WHERE NOT EXISTS (
SELECT *
FROM BirthDate AS b
WHERE p.PersonID = b.PersonID
);
В статье Дарвена представлены две явные таблицы, скажем, BirthDate
и BirthDateKnown
, но SQL не будет сильно отличаться, например. полусоединение с BirthDateKnown
вместо полуразницы с BirthDate
выше.
Обратите внимание, что в вышеприведенном случае используются JOIN
и INNER JOIN
только потому, что стандартные SQL-92 NATURAL JOIN
и UNION CORRESPONDING
не получили широкого применения в реальных продуктах SQL (не могу найти цитату, но IIRC Darwen был в основном ответственен последние два превращаются в Стандарт).
Кроме того, обратите внимание, что приведенный выше синтаксис выглядит многословно только потому, что SQL в общем случае многословен. В чистой реляционной алгебре это больше похоже на (псевдокод):
Person JOIN BirthDate UNION Person NOT MATCHING BirthDate ADD '1900-01-01' AS DateOfBirth;