在我开发的图书馆管理系统中,我有一张带有文学类型树的桌子。它们被编码为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
的情况下得到那些奇怪的结果。
有任何线索吗?
答案 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
是不必要的?)