mySQL ВЫБРАТЬ ИЗ таблицы ГДЕ ... И ... И ... И - PullRequest
0 голосов
/ 09 ноября 2011

У меня есть таблица «статей» со столбцами и данными:

article_id     title               body
1            This is the title   This is the body text
2            Another title       Another body text

Другая таблица "категория" с колонками и данными:

category_id    category
1              localnews
2              visible
3              first10

И таблица "категорий" с колонками и данными:

categories_id   article_id  category_id
1               1           1
2               1           2
3               1           3
4               2           1
5               2           3

Я хочу ВЫБРАТЬ строку (и), ГДЕ category.category_id = 1 И = 2 И = 3

Я использую:

SELECT articles.article_id, articles.title, articles.body, 
categories.article_id, categories.category_id 
FROM articles, categories 
WHERE articles.article_id = categories.article_id 
AND categories.article_id = 1 
AND categories.article_id = 2 
AND categories.article_id = 3 

но это не работает. Очевидно, что MySQL нуждается в другом синтаксисе. Может кто-нибудь помочь? Спасибо

Ответы [ 4 ]

3 голосов
/ 09 ноября 2011
SELECT 
   Articles.article_id, 
   COUNT( Categories.article_id ) AS total 
FROM CategoryArticles 
LEFT JOIN Articles USING (article_id)
WHERE 
   CategoryArticles.category_id IN (1,2,3)
GROUP BY CategoryArticles.article_id
HAVING  total = 3

Я использовал несколько разные имена для таблицы, потому что в вашем примере различие между category и categories трудно заметить.

1 голос
/ 09 ноября 2011

В дополнение к обычно используемому IN () и использованию счетчика HAVING, я бы заинтересовался разницей в производительности, выполнив множественное объединение следующим образом ...

SELECT STRAIGHT_JOIN
      articles.article_id, 
      articles.title, 
      articles.body
   FROM 
      categories c1
         JOIN articles
            on c1.article_id = articles.article_id
         JOIN categories c2
            on c1.article_id = c2.article_id
           AND c2.category_id = 2
         JOIN categories c3
            on c1.article_id = c3.article_id
           AND c3.category_id = 3
  WHERE
     c1.Category_ID = 1

Да, это может показаться неясным, но давайте подумаем об этом ... сделав ПЕРВЫЕ объединения в таблице категорий, где ОДНА из ваших конкретных категорий - ЭТОТ ПЕРВЫЙ ОТ экземпляра категорий должен быть представителем той категории, которая будет иметь наименьшая зернистость. Пример: Ваши категории «Местные новости», «Видимые» и «Первые» 10. В местных новостях, вероятно, будет больше всего записей, в то время как «Видимые» и «Первые 10» будут иметь еще меньше ... из них, которые будут иметь даже наименьшее количество записей. Используйте ЭТУ категорию в качестве предложения where.

Итак, скажем, у вас есть 100 000 статей и 90 000 в местных новостях, 45 000 в видимых и 12 000 в первых 10. Отправляя запрос только на те из 12 000, вы удаляете большую часть данных.

Путем присоединения к таблице статей и категориям AGAIN в качестве псевдонимов C2 и C3 соответственно на основе других условий, если они найдены, выполнены, если нет, исключены.

Опять же, мне интересно влияние на производительность. Я также хотел бы иметь составной индекс в таблице категорий на обоих (article_id, category_id)

1 голос
/ 09 ноября 2011

Столбец строки не может быть 1, 2 или 3 одновременно , что и предписывает AND. Используйте OR в вашем WHERE состоянии. Еще лучше - для удобства чтения - вы можете использовать IN:

SELECT ...
WHERE `categories`.`article_id` IN(1,2,3)
0 голосов
/ 09 ноября 2011

Значение не может быть всеми тремя значениями одновременно, поэтому вам лучше использовать предложение IN в вашем WHERE, чтобы определить, что вы хотите вернуть. Если у вас уже есть условие соединения, вы бы хотели вместо этого переместить его в предложение ON; то есть:

SELECT articles.article_id, articles.title, articles.body, categories.article_id, categories.category_id 
FROM articles
INNER JOIN categories ON articles.article_id = categories.article_id 
WHERE categories.article_id IN ( 1, 2, 3 )

Конечно, вы можете перейти к следующему шагу и сделать:

SELECT articles.article_id, articles.title, articles.body, category.category
FROM articles
INNER JOIN categories ON articles.article_id = categories.article_id 
INNER JOIN category ON categories.category_id = category.category_id
WHERE categories.article_id IN ( 1, 2, 3 )

Если вместо этого вы хотите показывать только статьи, которые появляются во всех трех категориях, то вы можете использовать такой подход, как:

SELECT articles.article_id, articles.title, articles.body
FROM articles
INNER JOIN categories AS c1
ON articles.article_id = c1.article_id 
AND   c1.category_id = 1
INNER JOIN categories AS c2
ON articles.article_id = c2.article_id 
AND   c2.category_id = 2
INNER JOIN categories AS c3
ON articles.article_id = c3.article_id 
AND   c3.category_id = 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...