Каков наилучший способ присоединиться к одному столу дважды?
Это немного сложно, но у меня есть 2 таблицы. Допустим, структура выглядит примерно так:
*Table1*
ID
PhoneNumber1
PhoneNumber2
*Table2*
PhoneNumber
SomeOtherField
таблицы могут быть объединены на основе таблицы 1.PhoneNumber1 - > Table2.Номер телефона или Таблица1.PhoneNumber2 - > Table2.Номер телефона.
Теперь я хочу получить результирующий набор, который содержит PhoneNumber1, SomeOtherField, который соответствует PhoneNumber1, PhoneNumber2 и SomeOtherField, который соответствует PhoneNumber2.
Я думал о 2 способах сделать это-либо путем присоединения к таблице дважды, либо путем присоединения один раз с или в предложении ON.
Способ 1:
SELECT t1.PhoneNumber1, t1.PhoneNumber2,
t2.SomeOtherFieldForPhone1, t3.someOtherFieldForPhone2
FROM Table1 t1
INNER JOIN Table2 t2
ON t2.PhoneNumber = t1.PhoneNumber1
INNER JOIN Table2 t3
ON t3.PhoneNumber = t1.PhoneNumber2
Это, кажется, работает.
Способ 2:
чтобы как-то иметь запрос, который выглядит немного так -
SELECT ...
FROM Table1
INNER JOIN Table2
ON Table1.PhoneNumber1 = Table2.PhoneNumber OR
Table1.PhoneNumber2 = Table2.PhoneNumber
Я не получил эту работу, и я не уверен, если есть способ сделать это.
каков наилучший способ добиться этого? Ни один из способов не кажется простым или интуитивный... Есть ли более простой способ сделать это? Как это требование в целом реализуется?
5 ответов:
во-первых, я бы попытался рефакторинг этих таблиц, чтобы уйти от использования телефонных номеров в качестве естественных ключей. Я не фанат естественных ключей и это отличный пример почему. Естественные ключи, особенно такие вещи, как номера телефонов, могут меняться и часто так. Обновление базы данных, когда это изменение произойдет, будет огромной, подверженной ошибкам головной болью. *
Способ 1 как вы описываете это ваш лучший выбор. Это выглядит немного лаконично из-за схемы именования и коротких псевдонимов но... сглаживание-это ваш друг, когда речь заходит о присоединении к одной и той же таблице несколько раз или использовании подзапросов и т. д.
Я бы просто убрал вещи немного:
SELECT t.PhoneNumber1, t.PhoneNumber2, t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2 FROM Table1 t JOIN Table2 t1 ON t1.PhoneNumber = t.PhoneNumber1 JOIN Table2 t2 ON t2.PhoneNumber = t.PhoneNumber2что я сделал:
- нет необходимости указывать внутренний - это подразумевается тем, что вы не указываете влево или вправо
- не N-суффикс вашей основной таблицы поиска
- N-суффикс псевдонимы таблицы, которые вы будете использовать несколько раз, чтобы сделать это очевидно
*один из способов избежать головной боли при обновлении естественных ключей-не указывать первичные ключи и ограничения внешнего ключа, что еще больше усугубляет проблемы с плохим дизайном БД. Я на самом деле видел это чаще, чем нет.
первый хорош, если только Phone1 или (более вероятно) phone2 не может быть null. В этом случае вы хотите использовать левое соединение вместо внутреннего соединения.
Это обычно плохой знак, когда у вас есть таблица с двумя полями номер телефона. Обычно это означает, что ваш дизайн базы данных является ошибочным.
первый метод является правильным подходом и будет делать то, что вам нужно. Однако с помощью внутренних соединений вы будете выбирать только строки из
Table1Если оба номера телефонов существуют вTable2. Вы можете сделатьLEFT JOINТак что все строкиTable1выбранные. Если номера телефонов не совпадают, тоSomeOtherFields будет null. Если вы хотите убедиться, что у вас есть хотя бы один соответствующий номер телефона, который вы могли бы сделатьWHERE t2.PhoneNumber IS NOT NULL OR t3.PhoneNumber IS NOT NULLвторой метод может иметь проблему: что бывает, если
Table2какPhoneNumber1иPhoneNumber2? Какая строка будет выбрана? В зависимости от ваших данных, внешние ключи и т. д. это может быть или не быть проблемой.
вы могли бы использовать
UNIONдля объединения двух соединений:SELECT Table1.PhoneNumber1 as PhoneNumber, Table2.SomeOtherField as OtherField FROM Table1 JOIN Table2 ON Table1.PhoneNumber1 = Table2.PhoneNumber UNION SELECT Table1.PhoneNumber2 as PhoneNumber, Table2.SomeOtherField as OtherField FROM Table1 JOIN Table2 ON Table1.PhoneNumber2 = Table2.PhoneNumber
моя проблема была в отображение записи, даже если нет или существует только один номер телефона (полная адресная книга). Поэтому я использовал левое соединение, которое берет все записи слева, даже если нет соответствующего справа. Для меня это работает в Microsoft Access SQL (они требуют скобки!)
SELECT t.PhoneNumber1, t.PhoneNumber2, t.PhoneNumber3 t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2, t3.someOtherFieldForPhone3 FROM ( ( Table1 AS t LEFT JOIN Table2 AS t3 ON t.PhoneNumber3 = t3.PhoneNumber ) LEFT JOIN Table2 AS t2 ON t.PhoneNumber2 = t2.PhoneNumber ) LEFT JOIN Table2 AS t1 ON t.PhoneNumber1 = t1.PhoneNumber;