douweibeng5219 2014-05-02 09:40
浏览 41
已采纳

MySQL查询(分层数据)返回错误的节点深度

I have a MySQL query that is supposed to select a number of hierarchical locations belonging to a certain company from a database table. Only one table is needed to be used.

The query works fine if all locations in the table belong to one company, but if I add any locations belonging to other companies, the calculated depth (level within a hierarchy calculated using the nested set model) is returned incorrect. The lastly created company locations still return correct results, but all previous companies return incorrect depth.

So I guess my query is somehow getting rows from companies other then the company in question and hence all results get messed up, however I just can't figure out why and where exactly its doing this.

I am using THIS article as my reference for hierarchical data (Nested Set Method) queries.

Here is the query:

//This query will return a result set with all 'locations' that are on and below the hierarchy level of
//the specified location. It will also add a depth field to each row which
//shows how deep each location is in relation to the named starting location.
//Any location name can be supplied, even the root location.
//This query uses three self-joins and a sub-query to determine the depth of each location in relation to the starting
//location.
"   SELECT location.location_id, location.location_name, location.location_company_id, location.location_active, (COUNT(parent.location_name) - (sub_tree.depth + 1))
    AS depth
    FROM locations AS location,
         locations AS parent,
         locations AS sub_parent,
         (
             SELECT location.location_id, (COUNT(parent.location_name) - 1) AS depth
             FROM locations AS location,
                 locations AS parent
                 WHERE location.lft
                 BETWEEN parent.lft
                 AND parent.rgt
                 AND location.location_id = 334
                 AND location.location_company_id = 1001
                 GROUP BY location.location_id
                 ORDER BY location.lft
         )
         AS sub_tree
    WHERE location.lft BETWEEN parent.lft AND parent.rgt
    AND location.lft BETWEEN sub_parent.lft AND sub_parent.rgt
    AND sub_parent.location_id = sub_tree.location_id
    AND location.location_company_id = 1001
    GROUP BY location.location_id
    ORDER BY location.lft;
"

This query works great when the data in the 'locations' table is as follows (one company locations only):

location_id location_name   location_company_id lft rgt location_active
    334   Company 1            1001              1   6        1
    335   Comp1 Loc1           1001              4   5        1
    336   Comp1 Loc2           1001              2   3        1

In this case the depth gets calculated correctly.

However, if I add more companies with some locations to the table then problems start occurring. By the way, the more companies with locations in the table, the bigger the depth inaccuracy. The first company gets most inaccurate depth, the second one gets only slightly inaccurate depth, and the last company gets correct depth. Here is a table with three company locations:

location_id location_name   location_company_id   lft    rgt   location_active
     334      Company 1             1001          1       14       1
     335      Comp1 Loc1            1001          12      13       1
     336      Comp1 Loc2            1001          10      11       1
     337      Company 2             1002          1       10       1
     338      Comp2 Loc1            1002          8       9        1
     339      Comp2 Loc2            1002          6       7        1
     340      Company 3             1003          1       6        1
     341      Comp3 Loc1            1003          4       5        1
     342      Comp3 Loc2            1003          2       3        1

What I fail to figure out is whether the data in the table is incorrect (lft and rgt) or the query itself is wrong and how to fix it.

Any help, tips or advice would be greatly appreciated.

  • 写回答

1条回答 默认 最新

  • duanjiao1256 2014-05-02 09:58
    关注

    You updated your lft and rgt values incorrectly.

    Comp1 has lft and rgt set from 1-14 where as Comp2 has it set from 1-10 This means that Comp1 has all locations from 1-14 and comp2 all locations from 1-10

    this should probably be 9-14 for Comp1 and 6-10 for Comp2

    Apart from that, now that the binary tree you are creating in mySQL is very poor on performance. Better would be to use DB that supports the WITH statement (e.g. DB2)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘