JOIN查询的奇怪行为

时间:2015-04-04 07:59:08

标签: mysql mariadb

在我开发的图书馆管理系统中,我有一张带有文学类型树的桌子。它们被编码为IP(代码2.诗歌,代码2.1。史诗,代码2.1.2。拉丁史诗等)。

类似IP的代码不仅可以计算特定类型,还可以计算其所有子类型。如果我想知道图书馆里有多少首诗,我所要做的就是计算2.%代码。

由于树将根据库的需要进行填充,当他们获得新书时,会有一个名为ord_vis的字段,指定行的可视化顺序(即关于行的新行) 1911年的意大利 - 土耳其战争必须在第一次世界大战和第二次世界大战前展示,即使是在六天战争之后插入的。)

树工作顺利,直到我决定使用以下查询计算标题数量:

SELECT  a.id, a.code, a.level, a.parent, a.text,
        GROUP_CONCAT( b.text ORDER BY  b.ord_vis SEPARATOR ', ' ) AS subs,
        COUNT( books.id ) AS total
    FROM  tree AS a
    LEFT JOIN  books ON books.code LIKE CONCAT( a.code, '%' )
    LEFT JOIN  tree AS b ON b.parent = a.id
      AND  b.level = a.level +1
    WHERE  a.parent =42 -- this value is the user query
    GROUP BY  a.id
    ORDER BY  a.ord_vis ASC

奇怪的是,如果total是> 0或NOT NULL,显示的subs数与total相同:有6本书和3个子类我得到sub类似" sub1,sub1,sub2, sub2,sub3,sub3"。

total为0时,subs会以正确的数字和顺序显示。

我用所有可用的JOIN选项测试了查询失败,我也试图改变JOIN和SELECT字段的顺序。

我解决了以这种方式修改获取潜艇的线的问题:GROUP_CONCAT(DISTINCT b.text ORDER BY b.ord_vis SEPARATOR ', ' ) AS subs但我想理解为什么在没有DISTINCT的情况下得到那些奇怪的结果。

有任何线索吗?

1 个答案:

答案 0 :(得分:1)

JOIN往往会爆炸行数。 DISTINCT是一种控制爆炸的方法。

另一种方法(有时可行)是给我们一个相关的子查询。这可能(或可能不)运行得更慢:

SELECT  a.id, a.code, a.level, a.parent, a.text, 
        ( SELECT  GROUP_CONCAT( text ORDER BY  ord_vis SEPARATOR ', ' )
            FROM  tree
            WHERE  parent = a.id
              AND  level = a.level +1 ) AS subs,
        COUNT( books.id ) AS total
    FROM  tree AS a
    LEFT JOIN  books ON books.code LIKE CONCAT( a.code, '%' )
    WHERE  a.parent =42 -- this value is the user query
    GROUP BY  a.id
    ORDER BY  a.ord_vis ASC 

(我怀疑LEFT是不必要的?)