Почему это левое соединение не показывает все данные из таблицы слева, которые не соответствуют таблице справа? (MySQL)

#mysql #join #left-join

#mysql #Присоединиться #левое соединение

Вопрос:

У меня есть следующий запрос, который должен выбирать все статьи из article_new, которые либо А) отсутствуют в ArticlesInCategories_New, либо Б) в нем, но не имеют CategoryID = 7, 8, 9, 10 или 11.

Удалив строки Category !=, я определил, что проблема заключается (по крайней мере) в том, что article_new не выбирает все из article_new, которого нет в ArticlesInCategories_New . Я все еще не совсем понимаю GroupBy, но я основывался на других вопросах, я попробовал GroupBy Articles_New.articleId , и это ничего не изменило.

     SELECT 
       DISTINCT Articles_New.ArticleID, 
       DATE_FORMAT(Articles_New.PublicationDate, '%c/%e/%Y') AS ReleaseDate, 
       Articles_New.Title, 
       Articles_New.Type, 
       Articles_New.URL
     FROM 
       Articles_New
        LEFT JOIN ArticlesInCategories_New
            ON ArticlesInCategories_New.ArticleID = Articles_New.ArticleID
     WHERE 
       PublicationDate >= DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND
       PublicationDate <= CURDATE() AND
       Articles_New.Public = '1'
       AND ArticlesInCategories_New.CategoryID != '7'
       AND ArticlesInCategories_New.CategoryID != '8'
       AND ArticlesInCategories_New.CategoryID != '9'
       AND ArticlesInCategories_New.CategoryID != '10'
       AND ArticlesInCategories_New.CategoryID != '11' 
     ORDER BY 
       Articles_New.PublicationDate DESC,
       Articles_New.ArticleID DESC
  

Ответ №1:

Вам нужны все строки, которые либо:
А) отсутствуют в ArticlesInCategories_New
Б) в ArticlesInCategories_New, но не имеют CategoryID = 7, 8, 9, 10 или 11.

 SELECT DISTINCT 
   Articles_New.ArticleID, 
   DATE_FORMAT(Articles_New.PublicationDate, '%c/%e/%Y') AS ReleaseDate, 
   Articles_New.Title, 
   Articles_New.Type, 
   Articles_New.URL
 FROM 
   Articles_New
    LEFT JOIN ArticlesInCategories_New
        ON ArticlesInCategories_New.ArticleID = Articles_New.ArticleID
 WHERE 
   (
     ArticlesInCategories_New.ArticleID IS NOT NULL AND
     PublicationDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND CURDATE()
     AND Articles_New.Public = '1'
     AND ArticlesInCategories_New.CategoryID NOT IN ('7','8','9','10','11')
   )
   OR 
   (
     ArticlesInCategories_New.ArticleID IS NULL
   )
 ORDER BY 
   Articles_New.PublicationDate DESC,
   Articles_New.ArticleID DESC
  

Комментарии:

1. Работает отлично, спасибо! Я не понимаю, хотя зачем ArticlesInCategories_New.ArticleID IS NULL это требуется. Разве это не цель использования a LEFT JOIN ?

2. @John, у тебя есть 2 условия. is null Тест проверяет первое условие: он возвращает все строки, для которых нет совпадений . Другой тест предназначен для второго условия. Там я добавил is not null , потому что вы заявили, что должно быть совпадение.

3. @John, левое соединение возвращает все строки в левой таблице (article_new), а данные для таблицы этих строк совпадают в правой таблице (ArticlesInCategories_New) {null для тех, которые не совпадают}

Ответ №2:

Вы описываете два набора статей, которые вы хотите, all the articles from Articles_New которые удовлетворяют одному из следующих:

  • А) не в ArticlesInCategories_New
  • Б) in ArticlesInCategories_New , но не имеют CategoryID = 7, 8, 9, 10 или 11.

Вы могли бы упростить этот сложный запрос, найдя эти два набора по отдельности, а затем объединив их с a UNION . Это позволит вам тестировать и отлаживать каждый из запросов отдельно.

Комментарии:

1. Без тестирования похоже, что ваш ответ сработает. Но действительно ли написание двух операторов и объединение их с помощью ‘UNION’ упрощает это? Это кажется таким же сложным

2. Мнения могут различаться, но я думаю, что важным преимуществом является то, что вы можете test and debug each of the queries separately .