1. 程式人生 > >mysql遞迴查詢,mysql中從子類ID查詢所有父類(做無限分類經常用到)

mysql遞迴查詢,mysql中從子類ID查詢所有父類(做無限分類經常用到)

由於mysql 不支援類似 oracle with ...connect的 遞迴查詢語法
之前一直以為類似的查詢要麼用儲存過程要麼只能用程式寫遞迴查詢.

現在發現原來一條sql語句也是可以搞定的

先來看資料表的結構如下:

id  name    parent_id 

--------------------------- 
1   Home        0 
2   About       1 
3   Contact     1 
4   Legal       2 
5   Privacy     4 
6   Products    1 
7   Support     1 
我要的要求是根據一個分類ID(這個分類ID可能是一個子分類),得到所有的父分類,下面是相應的SQL:

SELECT T2.id, T2.name 
FROM ( 
    SELECT 
        @r AS _id, 
        (SELECT @r := parent_id FROM table1 WHERE id = _id) AS parent_id, 
        @l := @l + 1 AS lvl 
    FROM 
        (SELECT @r := 5, @l := 0) vars, 
        table1 h 
    WHERE @r <> 0) T1 
JOIN table1 T2 
ON T1._id = T2.id 
ORDER BY T1.lvl DESC;

父類查詢所有子類函式

CREATE FUNCTION getChildeIds (rootId INT) RETURNS VARCHAR (1000) 
BEGIN
  DECLARE sTemp VARCHAR (1000) ;
  DECLARE sTempChd VARCHAR (1000) ;
  SET sTemp = '0' ;
  SET sTempChd = CAST(rootId AS CHAR) ;
  WHILE
SET sTemp = CONCAT(sTemp,',',sTempChd);
    SELECT 


      GROUP_CONCAT(子ID) INTO sTempChd 
    FROM
      platform_depart
    WHERE FIND_IN_SET(父id, sTempChd) > 0 ;
  END WHILE ;
  SET sTemp=substring(sTemp,3);
   RETURN sTemp;
END$$


FIND_IN_SET( ID, getChildeIds (ID) )

!FIND_IN_SET( ID, getChildeIds (ID) )



-- MySql 獲取當前節點及遞迴所有上級節點
-- 引數說明:resultField:查詢返回欄位,idd 要查詢的資源ID值,idFieldName ID欄位名,parentIdFieldName 上級ID欄位名,tableName 表名,isContainMySelf 是否包含自己
DROP procedure IF EXISTS pro_getParentList;
create procedure pro_getParentList(in resultField varchar(4000),in myid varchar(100),in idFieldName varchar(100),in parentIdFieldName varchar(100),in tableName varchar(100),isContainMySelf int)
begin
    drop table if exists tmpParent;
    CREATE    TABLE tmpParent(temId varchar(100)) ;
    set @tempParentId=myid;
  set @myDoflag=1;
WHILE @myDoflag>0  do
    set @ssss = CONCAT(' select ', parentIdFieldName, ', count(*) INTO  @tempParentId,@myDoflag from ',tableName ,' where ',idFieldName,'=','''',@tempParentId,'''');
        prepare strsql from @ssss;
        execute strsql;
    deallocate prepare strsql;    
    if(@myDoflag>0) THEN
      set @insertSql = CONCAT('INSERT into tmpParent(temId) values (',"'",@tempParentId,"'",')');
      prepare preSql1 from @insertSql;
      execute preSql1;
    deallocate prepare preSql1;
    end if;
end WHILE;
          
         IF (isContainMySelf=1) THEN
            INSERT into tmpParent(temId) values (myid);
         END IF;
 
            SET @fieldSql=concat(' SELECT ',resultField);
            set @strsql = CONCAT(@fieldSql,' from ', tableName,' s ',' inner join  tmpParent t on t.temId=s.',idFieldName,'  order by s.',idFieldName,'  asc');
            prepare preSql from @strsql;
            execute preSql;
  
end