2017-02-01 6 views
0

Как справиться с ситуацией, когда вы хотите использовать Left Join, поскольку данные могут быть или не существовать. Но если Left Join найдет некоторые данные, вы хотите ограничить эти данные, связанные слева, путем объединения данных, связанных слева, в другую таблицу? (Без удаления исходных данных из результатов).Влево Присоединиться к другим условиям/Присоединение

Возможно, это потребует дополнительных Join, Where или подзапроса.

Вот что я пробовал:

SELECT users.*, failed_logins.* 
FROM users 
LEFT JOIN failed_logins ON failed_logins.user_id = users.user_id 
INNER JOIN banned ON banned.ip_address = failed_logins.ip_address 

Но это вызывает никаких данных не будет отображаться, если нет данных в banned, что соответствует failed_logins.

Если есть нужный ряд в banned, мы хотим включить строку от banned и failed_logins. В противном случае строка из failed_logins и banned должна быть исключена. Но данные, взятые с users, всегда должны быть включены.

+1

Ваш вопрос непонятен мне .. пожалуйста, обновите свой запрос и добавьте правильный образец данных и ожидаемый результат. – scaisEdge

+0

Почему user.user_id должен быть равен emails.email_id? Возможно, вы можете добавить структуру таблиц, чтобы мы могли помочь вам –

+0

Спасибо за комментарии, обновили вопрос, чтобы быть как можно яснее. При необходимости добавим примерные данные позже, но на этот раз придется уйти. – Andrew

ответ

2

Условие в INNER JOIN должно содержать failed_logins.ip_address, чтобы иметь значение, отличное от NULL. Любые строки со значением NULL для этого столбца будут исключены. И это будет отрицать «изюминку» соединения до failed_logins. (Любая строка в users, что не имеет соответствующую строку в failed_logins, внешнее объединение изобретет фиктивную совпадающую строку из failed_logins, все столбцов в совпадающей фиктивной строке будет NULL.

Таким образом, мы должны были бы способ разрешить NULL значения failed_logins.ip_address должны быть возвращен.

Одним из вариантов были бы сделать, что внутреннее соединение внешнего соединения. То есть, заменить INNER с LEFT.

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


EDIT

После перечитывая вопрос, это все еще не ясно, какой результат мы хотим вернулся. Почему нам нужно посмотреть таблицу banned? «для фильтрации данных, если они существуют» на самом деле не объясняет спецификацию.

Если есть нужный ряд в banned, мы хотим, чтобы исключить строку из результатов? Или мы хотим вернуть строки, где соответствующая строка не существует в banned.


Followup

ли соединение между failed_logins и banned во-первых, в вложенное представление (или, производной таблицы использовать просторечии MySQL). А затем выполните внешнее соединение между users и производной таблицей.

В качестве примера:

SELECT users.* 
    , fl.* 
    FROM users 
    LEFT 
    JOIN (SELECT f.user_id 
       , f.ip_address 
      FROM failed_logins f 
      JOIN banned b 
      ON b.ip_address = f.ip_address 
     ) fl 
    ON fl.user_id = users.user_id 
ORDER BY users.user_id, fl.ip_address 

Исходные данные failed_logins образца:

user_id  ip_address 
---------- ------------ 
    111  127.0.0.1 
    111  192.168.0.1 
    222  127.0.0.1 
    333  192.168.0.1 
    444  4.4.4.4 

и banned выборки данных

ip_address 
---------- 
127.0.0.1 

и предполагающие users содержит пять строк, 111 через 555, тем запрос должен вернуть:

user_id user_id ip_address 
------- ------- ---------- 
111  111  127.0.0.1 
222  222  127.0.0.1 
333  (null) (null) 
444  (null) (null) 
555  (null) (null) 

Если это не соответствует спецификации, рассмотрите вопрос о предоставлении некоторых выборочных данных (включая примеры случаев строк, которые должны и не должны возвращаться) вместе с ожидаемым выходом.

+0

Спасибо за усилия, обновил вопрос, чтобы быть как можно яснее. При необходимости добавим примерные данные позже, но на этот раз придется уйти. – Andrew