1. 程式人生 > >MySql和Oracle的遞迴查詢

MySql和Oracle的遞迴查詢

        當資料庫中的表格屬於自關聯表的時候,當根據parent_id去查詢他所有的子集的時候(並且不知道樹結構都多少層),就需要遞迴查詢了.
        我們經常遇到的情況有省市縣三級聯動,總銀行和分支銀行.我們在建立表的時候:
        第一方面在主鍵ID上上做區分:例如江蘇省id為10,南京市的id為10110,可以給前端頁面一個很好的分類依據;
        第二方面我們會加一個欄位parent_id和他的上級有一個關聯,給後臺查詢提供依據;
        正常情況下是用不到遞迴查詢的,但是也有例外,比如圖書館欄位表,分層可能不止三級,不同類圖書分的層次數也不確定,當想查詢某一類圖書(“人文”)下的所有的圖書的時候,就需要遞迴了.
我只接觸過Oracle和MySql上的遞迴查詢,這裡做一個應用介紹;

1. 使用Oracle實現遞迴查詢

oracle比mysql要簡單的多,可以使用其內建函式
start with 條件1(一般為parent_id="xxx").....connect by prior 條件2 
(一般為id = parent_id注意順序不能亂,不可寫成parent_id=id)

案例
這裡寫圖片描述
sql語句

SELECT
    *
FROM
    "RC"."T_USER_TYPE" T START WITH T .PARENT_ID = 11 CONNECT BY PRIOR T .GUID = T .PARENT_ID;

結果
這裡寫圖片描述

2. 使用MySql實現遞迴查詢

mysql相對於Oracle就複雜一點,因為mysql沒有內建start
with 類似的函式,這時候我們就自定義個 一個函式,裡面依賴了mysql的CAST();
CONCAT();GROUP_CONCAT();FIND_IN_SET()函式.

這裡對上述函式先做一個簡單介紹,方便理解自定義函式:
1. cast()

Cast(欄位名 as 轉換的型別 ),其中型別可以為:

CHAR[(N)] 字元型 
DATE 日期型
DATETIME 日期和時間型
DECIMAL float型
SIGNED int
TIME 時間型

案例—>這些都是大家常用到的情形

select cast(date as signed) as date from  table1;
結果:date:20151103153126 select cast(date as char) as date from table1; 結果:date:2015-11-03 15:31:26 select cast(date as datetime) as date from table1; 結果:date:2015-11-03 15:31:26 select cast(date as date) as date from table1; 結果:date:2015-11-03 select cast(date as time) as date from table1; 結果:date:15:31:26 select cast(num as decimal(10, 2)) as num from table2 結果:num:20.00

2 . concat()

此函式和前端js的陣列Arrayconcat()類似,連結字串;
 concat('11','22','33')
 結果:112233

3 . group_concat()

通常與groupby一起用,將查詢出來的欄位拼接,預設以逗號分隔

普通查詢
mysql> select * from aa; 
+------+------+ 
| id| name | 
+------+------+ 
|1 | 11| 
|1 | 20| 
|1 | 23| 
|2 | 20| 
|3 | 23 | 
|3 | 300 | 

使用group_concat查詢
mysql> select id,group_concat(name) from aa group by id; 
+------+--------------------+ 
| id| group_concat(name) | 
+------+--------------------+ 
|1 | 11,20,23| 
|2 | 20 | 
|3 | 23,300| 

4 . find_in_set()函式

類似於StringUtils的containt方法,因為兩個引數本質都是字串;也類似於Conllection的
contain方法,因為strlist一般是以逗號分隔的字串很像陣列,而str更像其中的一個元素;

FIND_IN_SET(str,strlist)

看個例子就明白了
select FIND_IN_SET("a","a,b,c")
結果: 1

select FIND_IN_SET("a","a,b,c,a")
結果: 1

select FIND_IN_SET("z","a,b,c,a")
結果: 0

mysql內建函式介紹完了,現在要遞迴查詢

這一段是在一個大神部落格上改寫的(請諒解)
自定義一個函式 queryChildrenAreaInfo

-- 如果已經存在此函式就刪除
DROP FUNCTION IF EXISTS queryChildrenAreaInfo;
-- 建立函式
CREATE FUNCTION queryChildrenAreaInfo(areaId INT)
-- 定義返回型別
RETURNS VARCHAR(4000)
-- 方法體
BEGIN
-- 定義變數
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);

SET sTemp='$';
SET sTempChd = CAST(areaId AS CHAR);
-- 遞迴迴圈
WHILE sTempChd IS NOT NULL DO
SET sTemp= CONCAT(sTemp,',',sTempChd);
--- 查詢所有的id並拼接字串,條件是parent_id在此字串中,如果沒有了則sTempChd為null
SELECT GROUP_CONCAT(id) INTO sTempChd FROM f_user_type WHERE FIND_IN_SET(parent_Id,sTempChd)>0;
END WHILE;
RETURN sTemp;
END;


當呼叫此方法的時候,返回的是給定id對應的分類下的所有分類的的id的用逗號分隔的字串

select queryChildrenAreaInfo(11)
結果:$,11,11001,11002,11003,11004,11005,11006,11007,11009,11010,11011,11012,11013,11014,11021,11022,11023,11024,11025,11026,11027

我們查詢只需查id在此字串中即可(不可以用in,因為返回的是一個字串而不是"1101","1102")
SELECT * FROM f_user_type WHERE FIND_IN_SET(id,queryChildrenAreaInfo(11));

這裡寫圖片描述

相關推薦

Oracle 查詢:start with

 什麼時候用到start with ?    (1) 一張表中存放有目錄樹的相關資料(子類id , 父類id )    (2)但是想展示為父子型別的資料給前臺,或者列表(table)中,    (3) 這個時候就可以考

oracle查詢報錯

SELECT * FROM T_OrgCom t where t.systemcode = '04' and t.ENABLED = '1' START WITH t.id='00000000' CONNECT BY   PRIOR t.ID=t.pid 報錯:使用者資料中的co

oracle查詢最淺顯的用法

條件左邊的欄位為父親,就是向上查詢,左邊的欄位為孩子就是向下查詢。 --向上查詢,也就是指定某個節點開始,一直查到根節點,條件為 parent=child SELECT *   FROM CATALOG TCONNECT BY PRIOR T.PARENTID = T.ID

oracle查詢start with ... connect by 的使用

create table test_wx (id varchar2(30), pid varchar2(30), type varchar2(30) ); insert into test_wx (ID, PID, TYPE) values ('10', '0', 'A'

Oracle查詢start with connect by prior

一、基本語法 connect by遞迴查詢基本語法是: select 1 from 表格 start with ... connect by prior id = pId start with:表示以什麼為根節點,不加限制可以寫1=1,要以id為123的節點為根節點,就寫為start with id

ORACLE單行轉多行、ORACLE查詢

ORACLE單行轉多行 WITH TESTTABLE AS ( SELECT 'TEST1' GROUPNAME , 'A,B,C,D,E' VALUENAME FROM DUAL UNION ALL SELECT 'TEST2' GROUPNAME ,

令人迷糊的Oracle查詢(start with)

寫程式碼時碰到要弄清楚Oracle的role之間的傳遞關係,就是有role A的話,可以通過grant A to B,把A賦予給B,又通過grant B to C .那我想知道所有role中,有哪些role具有A的許可權. 上網一查發現有個遞迴查詢,不過都講的不是太詳細,而

oracle 查詢排序

有時候where查詢出的資料沒有層級關係,想要查詢的不光是是當前層的資料還要包括當前層以及當前層級以下的所有資料 SELECT * FROM pb_join ja INNER JOIN (SELECT org_id, state FROM

oracle 查詢整個路徑並行轉列組合成字串

遞迴查詢路徑: select * from t_db_organize connect by prior fartherid=id start with id='139312' order by id asc 行轉列: select replace(wm_concat(

查詢查詢

按照經驗在新增標頭檔案搜尋路徑的時候總結了以下幾點 路勁分為絕對路徑和相對路徑 本人建議多使用相對路徑,這樣工程遷移的時候會省心不少 絕對路徑尋找方法:點選工程某個檔案,右鍵“show in finder”開啟終端,cd 把資料夾拖入,即可出現一個路勁,這個就是絕對路徑 相對路徑即相對於當前工程檔案的路

oracle查詢查詢條件ID下得所有子集)

一、CREATE TABLE TBL_TEST   (   ID NUMBER,   NAME VARCHAR2(100 BYTE),   PID NUMBER DEFAULT

ORACLE查詢(適用於ID,PARENTID結構資料表)

oracle樹查詢的最重要的就是select…start with…connect by…prior語法了。依託於該語法,我們可以將一個表形結構的以樹的順序列出來。在下面列述了oracle中樹型查詢的常用查詢方式以及經常使用的與樹查詢相關的oracle特性函式等,在這裡只涉及到一張表中的樹查詢方式而不涉及多表

mysql單表查詢

一、向下遞迴: DROP FUNCTION IF EXISTS getAllChildren; CREATE FUNCTION queryChildrenAreaInfo(parentId INT) RETURNS VARCHAR(4000) BEGIN DE

oracle 查詢屬於本部門以及下屬部門

oracle使用遞迴查詢要使用 connect by語句 下面給出一個例項: select PUBCB_id,PUBCB001,PUBCB002 from TB_PUBCB start with PUBCB_id = 136 connect by prior PUBCB_

mysql如何做查詢!!

mysql的逆襲:如何做遞迴層次查詢 最近在做一個從oracle資料庫到mysql資料庫的移植,遇到一個這樣的問題      在Oracle 中我們知道有一個 Hierarchical Queries 通過CONNECT BY 我們可以方便的查了所有當前節點下的

Oracle 查詢詳解

建立表和主外來鍵 CREATE TABLE SC_DISTRICT ( ID NUMBER(10) NOT NULL, PARENT_ID NUMBER(10), NAME VARCHAR2(

Oracle查詢

對於oracle進行簡單樹查詢(遞迴查詢) DEPTID PAREDEPTID NAME NUMBER NUMBER CHAR (40 Byte) 部門id 父部門id(所屬部門id) 部門名稱 通過子節點向根節點追朔. Sql程式碼   select 

Oracle 查詢查詢

select o1.org_id, o1.org_name, o1.p_org_id from loss_pub_org o1 --where o1.org_level = '03'/*可以新增過

mysqloracle分頁查詢

mysql分頁 分頁查詢 使用 pan mysql分頁查詢 nbsp max 記錄 不能 MYSQL分頁查詢 方式1: select * from table order by id limit m, n;   該語句的意思為,查詢m+n條記錄,去掉前m

MySqlOracle查詢

        當資料庫中的表格屬於自關聯表的時候,當根據parent_id去查詢他所有的子集的時候(並且不知道樹結構都多少層),就需要遞迴查詢了.         我們經常遇到的情況有省市縣三級聯動,總銀行和分支銀行.我們在建立表的時候: