несколько AND на одном и том же соединенном столе coulmnn - PullRequest
1 голос
/ 11 марта 2012

У меня есть три изображения таблицы, теги изображения и теги. таблица изображений содержит информацию об изображениях, теги содержат информацию о тегах, а теги image_tags содержат отношения между изображениями и тегами, отношения между многими и многими. Я хочу фильтровать изображения на основе нескольких тегов с условием AND (не IN).

Я пробовал:

SELECT images.* FROM images
LEFT JOIN image_tags ON image_tags.image_id = images.id 
LEFT JOIN tags tag_0 ON image_tags.tag_id = tag_0.id
LEFT JOIN tags tag_1 ON image_tags.tag_id = tag_1.id
WHERE tag_0.tag = "tagme"
AND tag_1.tag = "excellent"
AND images.filesize > 0
GROUP BY images.id
ORDER BY images.posted DESC LIMIT 0, 40

И

SELECT images.* FROM images
LEFT JOIN image_tags ON image_tags.image_id = images.id 
LEFT JOIN tags ON image_tags.tag_id = tags.id
WHERE tags.tag = "tagme"
AND tags.tag = "excellent"
AND images.filesize > 0
GROUP BY images.id
ORDER BY images.posted DESC LIMIT 0, 40

Но ничего не сработало, оно всегда возвращает ноль результатов, хотя они существуют.

Ответы [ 2 ]

1 голос
/ 11 марта 2012

Ваш первый запрос, даже если он использует соединение LEFT, требует попадания в tags для обоих «tagme» и «отлично», потому что условие находится в предложении where.Переместите условие в предложение ON, например:

SELECT images.* FROM images
LEFT JOIN image_tags ON image_tags.image_id = images.id 
LEFT JOIN tags tag_0 ON image_tags.tag_id = tag_0.id AND tag_0.tag = 'tagme'
LEFT JOIN tags tag_1 ON image_tags.tag_id = tag_1.id AND tag_1.tag = 'excellent'
WHERE images.filesize > 0
GROUP BY images.id
ORDER BY images.posted DESC LIMIT 0, 40

Ваш второй запрос отклонен - ​​у него невыполнимое условие:

WHERE tags.tag = "tagme"
AND tags.tag = "excellent"

tags.tag не может быть и"tagme" и"отлично".

0 голосов
/ 11 марта 2012

Ни одна из ваших попыток не является правильной, хотя первая ближе к правильной.Чтобы отфильтровать теги так, как вы пытаетесь их отфильтровать, вам нужно дважды присоединиться к image_tags и объединить оба экземпляра tags, чтобы разделить экземпляры image_tags.И кажется, что вы хотите делать внутренние соединения, а не внешние соединения.Здесь:

SELECT i.*
FROM images i
  INNER JOIN image_tags it0 ON it0.image_id = i.id
    INNER JOIN tags t0 ON t0.id = it0.tag_id
  INNER JOIN image_tags it1 ON it1.image_id = i.id
    INNER JOIN tags t1 ON t1.id = it1.tag_id
WHERE i.filesize > 0
  AND t0.tag = 'tagme'
  AND t1.tag = 'excellent'
ORDER BY i.posted DESC
LIMIT 0, 40

Есть еще один способ сделать то же самое.Попробуйте выполнить следующее:

SELECT i.*
FROM images i
  INNER JOIN image_tags it ON it.image_id = i.id
    INNER JOIN tags t ON t.id = it.tag_id
WHERE i.filesize > 0
  AND t.tag IN ('tagme', 'excellent')
GROUP BY i.id
HAVING COUNT(DISTINCT i.tag) = 2
ORDER BY i.posted DESC
LIMIT 0, 40

Условие t.tag IN ('tagme', 'excellent') ограничивает допустимые теги указанным списком, а HAVING COUNT(DISTINCT i.tag) = 2 гарантирует, что изображение получило все из них.

...