Каков наилучший способ присоединиться к одному столу дважды?
Это немного сложно, но у меня есть 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
выбранные. Если номера телефонов не совпадают, тоSomeOtherField
s будет 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;