MySQL объединяется с предложением where


131

У меня есть два стола, к которым я хочу присоединиться.

Мне нужны все категории в таблице категорий, а также все категории, на которые подписан пользователь, в таблице category_subscriptions.

по сути, это мой запрос:

SELECT *
FROM categories
LEFT JOIN user_category_subscriptions 
     ON user_category_subscriptions.category_id = categories.category_id

Это работает нормально, однако я хочу добавить предложение where в конце запроса, которое затем по существу делает его внутренним / равным соединением.

   SELECT *
    FROM categories
    LEFT JOIN user_category_subscriptions 
         ON user_category_subscriptions.category_id = categories.category_id 
   WHERE user_category_subscriptions.user_id = 1

Как мне получить все категории, а также все категории, на которые подписан конкретный пользователь, используя только один запрос?

category_id является ключом как в таблице категорий, так и в user_category_subscriptions. user_id, находящийся в таблице user_category_subscriptions.

Спасибо


Я считаю, что это называется «правильное соединение», если я не ошибаюсь?
Тайлер Картер,

@TylerCarter, вы наверняка ошиблись :)
Scooter Daraf

Ответы:


287

Вам нужно указать это в joinпредложении, а не в where:

SELECT *
FROM categories
LEFT JOIN user_category_subscriptions ON 
    user_category_subscriptions.category_id = categories.category_id
    and user_category_subscriptions.user_id =1

Смотрите, с помощью inner joinвставки предложения в joinили whereэквивалентно. Однако с an outer joinони сильно отличаются.

В качестве joinусловия вы указываете набор строк, который вы будете присоединять к таблице. Это означает , что он оценивает user_id = 1первый и принимает подмножество user_category_subscriptionsс user_idиз 1присоединиться ко всем строкам categories. Это даст вам все строки, в categoriesто время как только те categories, на которые этот конкретный пользователь подписался, будут иметь какую-либо информацию в user_category_subscriptionsстолбцах. Конечно, все остальные categoriesбудут заполнены nullв user_category_subscriptionsстолбцах.

И наоборот, whereпредложение выполняет соединение, а затем сокращает набор строк. Итак, это выполняет все соединения, а затем удаляет все строки, где user_idне равны 1. У вас остался неэффективный способ получить inner join.

Надеюсь, это поможет!


2
Красиво поставленный вопрос и красиво поставленный ответ! сэкономил мое время. большое спасибо!
Gaurav Phapale

1
Я так сильно тебя люблю, Эрик, ты спас меня от слез: D
Рахил

С другой стороны, если я хочу производить чистые данные для пользователей, второй (где) способ более уместен. Это правильно?
vlr

1
Привет, можем ли мы отказаться от user_category_subscriptions.user_id имеет значение null. Для получения идентификатора детали в таблице A, имеющей идентификатор null в таблице B
Веереш123,

@ Veeresh123, а что такое Aи Bстол? Вы можете перефразировать свой вопрос?
Istiaque Ahmed

11

Попробуй это

  SELECT *
    FROM categories
    LEFT JOIN user_category_subscriptions 
         ON user_category_subscriptions.category_id = categories.category_id 
   WHERE user_category_subscriptions.user_id = 1 
          or user_category_subscriptions.user_id is null

Если я все еще получаю ту же ошибку, используя этот код, что мне искать дальше.
Джек Франзен,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.