MySQL SELECT-запрос с последовательными условиями фильтрации - PullRequest
1 голос
/ 10 января 2012

Надеюсь, название не так запутанно - честно сказал, что понятия не имел, как лучше объяснить мою проблему в одной строке :-) (и Google это правильно BTW)

Таблица 'group' структурирована как вложенный набор для создания меню дерева. Статьи в таблице «article» ссылаются на идентификаторы таких групповых элементов, чтобы - хорошо - сгруппировать их:

Table 'article'                     Table 'group'
id   |   article      |   groupid           id   |  title    |   left    |   right
1    |   Bowl         |   2                 1    |  material |   1       |   6
2    |   Bowl         |   5                 2    |  wood     |   2       |   3
3    |   Cube         |   3                 3    |  steel    |   4       |   5
4    |   Cube         |   6                 4    |  shape    |   6       |   13
5    |   Bowl         |  10                 5    |  circle   |   7       |   8
6    |   Pyramid      |   2                 6    |  square   |   9       |   10
7    |   Pyramid      |   3                 7    |  rectangle|   11      |   12
8    |   Pyramid      |  11                 8    |  color    |   14      |   21
9    |   Bowl         |  11                 9    |  red      |   15      |   16
10   |   Cube         |   9                10    |  green    |   17      |   18
11   |   Pyramid      |   9                11    |  blue     |   19      |   20

Чтобы выбрать любую комбинацию элементов группы, у меня просто есть запрос с указанием диапазона от group.left до group.right, что дает мне набор group.id, который я могу сравнить с article.groupid. Следующее утверждение отвечает на все статьи, состоящие из дерева:

SELECT
   a.article
FROM
   article AS a
LEFT JOIN 
   group AS g
ON (
      (
         2 >= g.left
      AND
         3 <= g.right
      AND
         g.id = a.groupid
      )
   )
GROUP BY
   a.article

Теперь мой вопрос: как мне создать запрос, который отвечает, например, Все изделия, которые состоят из дерева И имеют ЛЮБОЙ цвет? Я ожидал, что повторные составные подзапросы в предложении WHERE позволят заключить сделку:

SELECT
    a.article
FROM
    article AS a
WHERE
    a.groupid IN
        (
            SELECT
                CONCAT(g.id) AS gr
            FROM
                group AS g
            WHERE
                (
                    2 >= g.left 
                AND
                    3 <= g.right
                )
        )
AND
    a.groupid IN
        (
            SELECT
                CONCAT(g.id) AS gr
            FROM
                group AS g
            WHERE
                (
                    14 >= g.left 
                AND
                    21 <= g.right
                )
        )

На этот запрос нет ответа. Кстати, мне не нравятся подзапросы, но многие попытки с JOINS и Sub-JOINS не сработали. Мой разум кружится - какие-нибудь советы от вас, ребята?

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 января 2012

Проблема не в SQL;вы запрашиваете записи с groupid между 2 и 3 в первом разделе и между 14 и 21 во втором.Ни одна запись не может соответствовать этому критерию.

Может быть, вы действительно хотите найти все деревянные изделия, все цветные и затем найти все в обоих.

0 голосов
/ 10 января 2012

отредактировано: сейчас работает. Проверьте это здесь (но в MSSQL)

Первый подход, основанный на вашем запросе, проблема в ненормализованном дизайне. Для выполнения запроса вы должны проверить , если существует строка для статей с таким же именем , которая ссылается на тип свойства:

SELECT
    distinct a.article
FROM
    article AS a
WHERE
    exists 
      (      
           SELECT
                1
            FROM
                group AS g
            INNER JOIN
                article as a2
                on g.id = a2.groupid
            WHERE 
                a2.article = a.article and
                (2 <= g.left AND 3 >= g.right)
       ) and
      exists (
           SELECT
                1
            FROM
                group AS g
            INNER JOIN
                article as a2
                on g.id = a2.groupid
            WHERE 
                a2.article = a.article and
                (14 <= g.left AND 21 >= g.right)
        )

Отредактированный

OP использует вложенные множества. Но, возможно, таблица статьи все еще не очень хорошо нормализована. Предлагаю принять во внимание этот дизайн:

article( id, name )
groupNestedSet( id, title, left, right )
article_group( idArticle, idGroup)

выборка нормализованных данных:

article( id, name )
1, Bowl   (only one time)
3, Cube   (also only one time)

groupNestedSet( id, title, left, right )
-- your data --

article_group( idArticle, idGroup)
1, 2
1, 5
3, 3
3, 5
...
...