MYSQL Inner Join с 2 предложениями ON - PullRequest
1 голос
/ 18 ноября 2009

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

Пользователи

id (Primary Key)    
name (Varchar 255)
residential_id (foreign key)
postal_id (foreign key)

Адрес

id (primary key)
type (enum of R and P)
street (varchar 255)
suburb (varchar 255)

Я пытаюсь выполнить внутреннее объединение, поэтому я получаю набор результатов, который выглядит следующим образом.

id - имя - residential_street - residential_suburb, postal_street, postal_suburb

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

Мой синтаксис SQL

SELECT * FROM users 
LEFT JOIN address
ON (users.residential_id = address.id AND users.postal_id = address.id)

EDIT. Как уже отмечалось, мой дизайн БД довольно плохой, и я стремлюсь его улучшить. Главное, чего я пытаюсь достичь, - это то, что я могу хранить данные о человеке вместе с соответствующим адресом проживания и почтовым адресом. Я никогда не буду расширять базу данных, чтобы включить, например, рабочий адрес, так что надеюсь, что это уменьшит сложность таблицы.

Ответы [ 4 ]

2 голосов
/ 18 ноября 2009

Предполагается, что

  1. столбец «id» в адресе является внешним ключом таблицы пользователя.
  2. в таблице адресов есть столбец addressType, который отличает почтовое от места жительства

То, что вы хотите:

select 
  u.*, 
  res.street residential_street,
  res.suburb residential_suburb,
  pos.street postal_street,
  pos.suburb postal_suburb
from users u
    left join address res on u.id=res.id and res.addressType='R'
    left join address pos on u.id=pos.id and pos.addressType='P'

Ключ в том, что вы должны присоединиться к таблице адресов ДВАЖДЫ. Дискриминатор типа адреса необходим, чтобы каждое соединение выбирало только соответствующий тип адреса. Если ваша схема отличается, пожалуйста, уточните, и я изменю свой ответ.

0 голосов
/ 18 ноября 2009

@ m3mbran3 мое предложение - сбросить поля residential_id и postal_id от пользователей

Пользователи

id (Primary Key)    
name (Varchar 255)

Адрес

id (if required, otherwise primary key is combo of userid,type)
user_id
type (enum of R and P)
street (varchar 255)
suburb (varchar 255)

Тогда вы вернулись к

SELECT u.id,
       u.name,
       ar.street residential_street,
       ar.suburb residential_suburb,
       ap.street postal_street,
       ap.suburb postal_suburb
FROM users u
LEFT JOIN address ar 
           ON u.id = ar.user_id
           AND ar.type = 'R'
LEFT JOIN address ap 
           ON u.id = ap.user_id
           AND ap.type = 'P'

вариант предложения @Cletus. Помните, что если у пользователя есть адрес места жительства и нет почтового адреса, или наоборот, могут быть значения NULL

0 голосов
/ 18 ноября 2009

Это относительно просто. Вам просто нужно присоединиться к таблице адресов дважды.

SELECT u.id,
       u.name,
       ar.street residential_atreet,
       ar.suburb residential_suburb,
       ap.street postal_street,
       ap.suburb postal_suburb
FROM users u
LEFT JOIN address ar ON u.residential = ar.id
LEFT JOIN address ap ON u.postal = ap.id

Я не одобряю такую ​​модель данных. Вместо этого я бы предложил иметь поле типа адреса и иметь отношение один ко многим (внешний ключ user.id в таблице адресов).

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

Одно предложение: поскольку резидентный и почтовый являются внешними ключами, попробуйте назвать их как таковые (например, residential_id и postal_id), чтобы было понятнее при чтении SQL.

0 голосов
/ 18 ноября 2009

Вы проверяете, равен ли адрес столбца идентификатору, я не думаю, что это будет так в любом случае.

...