Deeply nested subqueries for traversing trees in MySQL

狂风中的少年 提交于 2019-12-05 15:58:58

Does this work?

select r0.id 
  from my_table as r0 
  join my_table as r1 on(r0.parent_id = r1.id) 
  join my_table as r2 on(r1.parent_id = r2.id)
 where r0.alias='nickf'
   and r1.alias='admins'
   and r2.alias='users'
   and r2.parent_id is null

Seems to me there is not really a need for nested subqueries ..

or am I wrong, missing something?

I wondered about this myself, and was looking for something that didn't get slower as you went deeper (meaning more levels in both options above.) The problem I have with "my version", is that it has to create every possible path before it narrows the result down to the one you're actually searching for... so I think lexu's version should outperform mine even for very large nesting because it's a simple join, but I'm hoping someone might see it and wish to expand on it further.

Also, this way of doing it would definitely benefit from a stored proc, and/or a view of the 'paths' part of it (without the HAVING clause). Perhaps with those it is a better solution, but I unfortunately don't know enough at this time about SQL performance to say for sure. I can say that mine gets slower as the data (number of possible combination of paths) gets larger, but with a view (since the result is cached, and using that to narrow it down) it seems fast (the largest data set I found was 370 total, at some point I'll create a much larger set to test.)

SELECT node.id, GROUP_CONCAT(parent.alias
                 ORDER BY parent.lft SEPARATOR '.') AS path_name
FROM my_table AS node, my_table AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rght
GROUP BY node.id HAVING path_name = 'users.admins.nickf'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!