2012-06-26 2 views
0

Я довольно любитель, когда дело доходит до написания SQL, так что, возможно, это просто для кого-то? У меня есть две таблицы следующим образом:Присоединяйтесь к двум таблицам, содержащим два внешних ключа

Table1 - ИмяУстройства, DeviceID, AlternateID

  • MyPhone, 333, AAA
  • HerPhone, 444, CCC

Table2 - PhoneID , ProgramName

  • 333, AngryBirds
  • CCC, Evernote

Как вы можете видеть, Table2 использует два разных типа PhoneID из Table1 (DeviceID и AlternateID). Я ищу в SQL заявление, что приведет к выходу, как:

  • MyPhone, AngryBirds
  • HerPhone, Evernote

признательна за любую помощь.

Приветствия, Все

+0

Возможные дублируют http://stackoverflow.com/questions/2462111/mysql-inner-join-two-table-over-two-keys – Kermit

+0

Не уверен, но вы могли бы дать ему попробовать: 'Select DeviceName, ProgramName FROM table1, table2 WHERE DeviceID IN (PhoneId, AlternateID) ' –

ответ

3
SELECT deviceName, programName 
FROM table2 t2 
JOIN table1 t1 
ON(t1.DeviceID=t2.PhoneID OR t1.AlternateID=t2.PhoneID) 

или (менее читаемым, но короче)

SELECT deviceName, programName 
FROM table2 t2 
JOIN table1 t1 
ON(t2.PhoneID IN (t1.DeviceID, t1.AlternateID)) 

Тем не менее, если DeviceIDs и AlternateIDs из того же набора, вы должны рассмотреть рефакторинга базы данных: Что делать, если устройство может иметь несколько действительных идентификаторов, а не только два?

+0

Отлично. Большое спасибо за быстрый ответ. Привет, Марк. – user1484093

+0

Что делать, если идентификатор DeviceID и AlternateID для данной строки определены в таблице 2? Это приведет к 2 рядам. Это то, чего хочет OP? Не уверен. – dbenham

0

Что делать, если оба 333 и AAA определены в таблице 2? Я предполагаю, что вы хотите только хотите один ряд вернулся в DeviceName, что означает, что вам нужно, чтобы присоединиться к таблице 2 раза с использованием внешних соединений:

select DeviceName, 
     t2a.ProgramName, 
     t2b.ProgramName as AltProgramName 
    from table1 t1 
    left outer join table2 t2a 
    on t1.DeviceID = t2a.PhoneID 
    left outer join table2 t2b 
    on t1.AlternateID = t2b.PhoneID 

Если вы хотите перечислить только один ProgramName, и может устанавливать приоритет, какой использовать в случае, если оба присутствуют, вы можете сделать следующее: (при условии, DeviceID козыри AlternateID)

select DeviceName, 
     coalesce(t2a.ProgramName, t2b.ProgramName) as AltProgramName 
    from table1 t1 
    left outer join table2 t2a 
    on t1.DeviceID = t2a.PhoneID 
    left outer join table2 t2b 
    on t1.AlternateID = t2b.PhoneID 

Если вы хотите, 1-й столбец программы всегда содержит значение, и только перечислить значение в 2-й столбец, если оба они присутствуют, то

select DeviceName, 
     coalesce(t2a.ProgramName, t2b.ProgramName) as ProgramName1, 
     case when t2a.ProgramName is not null then t2b.ProgramName end as ProgramName2 
    from table1 t1 
    left outer join table2 t2a 
    on t1.DeviceID = t2a.PhoneID 
    left outer join table2 t2b 
    on t1.AlternateID = t2b.PhoneID 


EDIT

Я предположил запрос использовался для целей отчетности, в этом случае вы, скорее всего, хочу только одну строку для каждого устройства.

Я только понял, почему OP может потребовать несколько строк, возвращаемых на устройство. Если запрос используется для определения представления для поиска устройств по имени, то требуется несколько строк.

Jan's answer отлично подходит для просмотра. Однако он может работать или не работать должным образом в зависимости от оптимизатора запросов базы данных и размера таблиц. Если таблицы очень большие, тогда вам понадобится индексированный поиск. Соединение с условием ИЛИ может исключить индексированный поиск в некоторых системах. Эквивалентный запрос с использованием UNION ALL может поддерживать индексированный поиск в других системах.

select DeviceName, 
     ProgramName 
    from table1 t1 
    join table2 t2 
    on t1.DeviceID = t2.PhoneID 
union all 
select DeviceName, 
     ProgramName 
    from table1 t1 
    join table2 t2 
    on t1.AlternateID = t2.PhoneID 
Смежные вопросы