具有排序过滤条件的 MySQL SELECT 查询

发布于 2024-12-25 13:25:55 字数 2335 浏览 1 评论 0原文

希望标题没有那么令人困惑 - 老实说,我不知道如何更好地用一行解释我的问题:-)(顺便说一句,谷歌正确地解释了它)

表“组”被构造为嵌套集来创建树形菜单。表“文章”中的文章引用此类组元素的 ID,以便对它们进行分组:

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 的许多努力都没有奏效。 我的脑子在旋转——你们有什么建议吗?

谢谢

Hope the title is not that confusing - honestly said I had no idea how to better explain my problem in a single line :-) (and Google it properly BTW)

A table 'group' is structured as a nested set to create tree menues. Articles in a table 'article' reference to ID of such group element to - well - group them:

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

To select any combination of group elements, I simply have a query mentioning a range from group.left to group.right, giving me a set of group.id that I can compare with article.groupid.
Following statement responds all articles consisting of wood:

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

Now my question: how should I create a query, that responds with e.g. all articles that consist of wood AND have ANY color?
I expected that repeating concatenated subqueries in the WHERE clause would make the deal:

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
                )
        )

This query responds no result. BTW I dont like subqueries but many efforts with JOINS and Sub-JOINS did not work as well.
My mind is spinning - any tips from you guys?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦在深巷 2025-01-01 13:25:55

已编辑:现在正在工作。 在这里测试(但在 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)
        )

Edited

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
...

edited: now working. Test it here (but in MSSQL)

First approach based on your query, problem comes from non well normalized design. To do the query you will to check if exists a row on articles with same name that references a kind of property:

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)
        )

Edited

OP uses nested sets. But perhaps article's table is still not well normalized. I suggest to take in consideration this design:

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

sample normalized data:

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
...
听,心雨的声音 2025-01-01 13:25:55

问题不在于 SQL,而在于 SQL。您正在请求 groupid 介于 2 和 之间的记录第一部分中的 3,第二部分中的 14 和 21 之间的 AND。没有记录可以符合该标准。

也许您真正想要的是找到所有木质物品、所有彩色物品,然后找到两者中的所有物品。

The problem isn't the SQL; you're asking for records with a groupid between 2 & 3 in the first section, AND between 14 and 21 in the second. No record can match that criteria.

Maybe what you really want is to find all articles that are wood, all those that are color, and then find all that are in both.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文