鍍金池/ 問答/數(shù)據(jù)庫/ MySQL 子類節(jié)點查詢

MySQL 子類節(jié)點查詢

最近在面試看到一個很有趣的問題, 想征集一下大家有什么更好的思路來實現(xiàn)。。

  • 有兩張數(shù)據(jù)表: depts, users

其中第一張:

id parent_id type_id dept_name
1 0 1 TG
2 0 1 SG
3 1 2 設(shè)計部
4 1 2 研發(fā)部
5 2 1 產(chǎn)品部
6 1 5 運維安全線
7 6 2 安全平臺部
8 6 2 網(wǎng)絡(luò)平臺部

第二張:

id dept_id user_name
1 3 小明
2 3 小紅
3 3 小張
4 4 小王
5 4 老張
6 4 小黑
7 5 大黃
8 7 大蝦
9 7 零七
10 8 天空
11 8 瑪麗
  • 要求找出 表中 TG的所有員工。

我想到的最便捷的方式是。。添加字段。。path.
(例如 安全平臺部 path:0-1-6-7), 但是原題是上不允許這樣的做的, 如果要Join 表的話,可能需要遞歸操作。。。所以想讓大家看看有什么好的思路。。

回答
編輯回答
吢丕

mysql模擬遞歸查詢
查詢TG下的所有部門,加一個paths like ',0,1'就可以了。

SELECT id AS ID,pid AS 父ID ,levels AS 父到子之間級數(shù), paths AS 父到子路徑 FROM (
    SELECT id,pid,
        @le:= IF (pid = 0 ,0,
        IF( LOCATE( CONCAT('|',pid,':'),@pathlevel) > 0  ,
        SUBSTRING_INDEX( SUBSTRING_INDEX(@pathlevel,CONCAT('|',pid,':'),-1),'|',1) +1
        ,@le+1) ) levels
        , @pathlevel:= CONCAT(@pathlevel,'|',id,':', @le ,'|') pathlevel
        , @pathnodes:= IF( pid =0,',0',
        CONCAT_WS(',',
        IF( LOCATE( CONCAT('|',pid,':'),@pathall) > 0  ,
        SUBSTRING_INDEX( SUBSTRING_INDEX(@pathall,CONCAT('|',pid,':'),-1),'|',1)
        ,@pathnodes ) ,pid  ) )paths
        ,@pathall:=CONCAT(@pathall,'|',id,':', @pathnodes ,'|') pathall
    FROM  treenodes,
    (SELECT @le:=0,@pathlevel:='', @pathall:='',@pathnodes:='') vv
    ORDER BY  pid,id
) src
ORDER BY id
2017年12月11日 08:03
編輯回答
故人嘆

select user.*,dept.dept_name from user join dept on user.dept_id=dept.id where dept.dept_name='TG';

2017年11月27日 16:29
編輯回答
赱丅呿

sql不好處理的,你這個是層層遞進的,這種循環(huán)處理要放在代碼里面做才好的

2017年7月17日 09:20
編輯回答
傲嬌范

以前做過類似的查詢,是關(guān)于商品分類的,不過當時用的是MySQL自定義函數(shù)里面寫的遞歸,實現(xiàn)比較簡單。這里如果只用一句SQL查詢,只能利用SQL變量做文章了。大致說下實現(xiàn)思路:

  • 按parent_id從小到大遍歷depts所有記錄,不斷拼接@all_path變量,遍歷完之后,取最后一條記錄,3,4,7,8,6,1,:,5,2,

  • 很顯然,上面每個根節(jié)點為0的都是分號分隔了,根據(jù)TG的id=1再次做一個字符串處理,得到1,3,4,7,8,6

  • 最后聯(lián)合users表查詢即可

SELECT 
    u.*
FROM
    depts AS d,
    users AS u,
    (SELECT 
        depts_node
    FROM
        (SELECT 
        @auto_id:=@auto_id + 1 AS auto_id,
            @all_path:=IF(parent_id = 0, CONCAT(@all_path, ':,', id, ','), REPLACE(@all_path, CONCAT(',', parent_id, ','), CONCAT(',', id, ',', parent_id, ','))) AS depts_node
    FROM
        depts, (SELECT @auto_id:=0, @all_path:='') vv
    ORDER BY parent_id ASC) AS all_depts
    ORDER BY auto_id DESC
    LIMIT 0 , 1) AS f
WHERE
    d.dept_name = 'TG'
        AND FIND_IN_SET(u.dept_id,
            CONCAT(d.id,
                    SUBSTRING_INDEX(SUBSTRING_INDEX(f.depts_node, CONCAT(',', d.id, ','), 1),
                            ':',
                            - 1)))
2017年9月18日 21:20
編輯回答
乖乖瀦
SELECT [users].Id,[users].user_name FROM [users] LEFT JOIN [depts] ON  [users].dept_id=[depts].Id WHERE [depts].dept_name='TG'

--不知道我理解對沒有、
2017年3月2日 10:54