【问题标题】:MySQL SELECT query with sequenced filter conditions具有排序过滤条件的 MySQL SELECT 查询
【发布时间】:2012-01-09 22:21:46
【问题描述】:

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

表“组”被构造为嵌套集以创建树形菜单。表“文章”中的文章引用此类组元素的 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 的许多努力都没有奏效。 我的大脑在旋转——你们有什么建议吗?

谢谢

【问题讨论】:

  • 为什么要指定 rightleft 值?你不能只加入group.id 属性吗?有什么办法可以改变你的架构,因为它似乎在与你战斗而不是帮助你?
  • 不。没有文章提到“材料”、“形状”或“颜色”(ID 1、4 和 8)——这些是树形菜单标题,但我需要能够捕获与此类标题的所有元素相关的文章。跨度>
  • 您应该如何区分什么是标头和什么是标头类型?除非你硬编码标题的 id,否则似乎会有一些问题。
  • 左/右坐标定义每条记录的级别和从属关系 - 参见嵌套集模型

标签: mysql select sequence where


【解决方案1】:

已编辑:现在工作。 Test it here (but in 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
...

【讨论】:

  • 什么是设计中的“未标准化”?
  • 您从组表中删除了层次结构定义。您也不知道 article 列实际上是否不是文章的标题,因此为其创建单独的实体是没有意义的。
  • @a_horse_with_no_name,通过良好的规范化设计,查询将非常简单!
  • 我仍然认为 article_property 可能过头了。但是只有 OP 可以回答这个问题——从样本数据来看,你可能是对的,但你也可能是错的。顺便说一句:在 MySQL 中为层次结构使用邻接模型并不是一个好主意,因为 MySQL 仍然不支持层次查询(也称为递归 CTE)
  • @danihp 感谢到目前为止,但没有成功。关于规范化的一句话:实际表格的结构与您建议的完全一样 - 我只是用文章名称替换了 idArticle 并在这篇文章中留下了第 3 个表格以便更清楚
【解决方案2】:

问题不在于 SQL;您在第一部分中要求 groupid 介于 2 和 3 之间的记录,并且在第二部分中要求介于 14 和 21 之间的记录。没有记录可以符合该条件。

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

【讨论】:

  • 是的 - 现在我可以看到了。在 PHP 中,我首先会针对 2&3 进行查询,然后使用此结果针对 14&21 进行查询。是否可以将其组合成一个查询?
  • 当然;只需在每个材料的查询之间进行 JOIN;结果应该是两者中的文章列表。
猜你喜欢
  • 2015-10-28
  • 2016-05-22
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多