最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

mysql巧妙化解遞歸查詢樹形數(shù)據(jù) | 純sql

2023-03-07 17:29 作者:兩年半的java練習(xí)生  | 我要投稿

前言

  • 開發(fā)中樹形結(jié)構(gòu)應(yīng)該是很常見的一種數(shù)據(jù)結(jié)構(gòu)了。而在數(shù)據(jù)庫方面往往也都伴隨相應(yīng)的樹形設(shè)計(jì)。在?mysql?中通過?parent_id?來綁定其上游,從而達(dá)到樹形結(jié)構(gòu)的存儲,但是在查詢的過程中就需要我們將?List?列表轉(zhuǎn)成我們理想中的?Tree?樹。

構(gòu)建樹

  • 相信大部分我們 都是通過 Java 來處理的。 其中 getParentLocation 就是用遞歸不斷的去構(gòu)建上下級關(guān)系。這種方式也是我比較推薦的,因?yàn)檫@樣就把職責(zé)分的很清楚 Java 負(fù)責(zé)處理業(yè)務(wù) ,數(shù)據(jù)庫 就僅僅用來做數(shù)據(jù)的持久化,這也方便我們對數(shù)據(jù)庫切換與升級。否則在更換其他數(shù)據(jù)庫時(shí)還需要考慮是否支持遞歸屬性。

  • 有的時(shí)候?yàn)榱四軌蛄慨a(chǎn)化,這里我也針對項(xiàng)目的場景利用泛型進(jìn)行一次封裝。有興趣可以自己針對自己的項(xiàng)目場景進(jìn)行封裝。這樣樹形與列表的轉(zhuǎn)換就無須每次冗余了。然而今天我們的重點(diǎn)是如何利用 mysql 來實(shí)現(xiàn)遞歸查詢, 雖然這種方式個(gè)人不推薦使用,但我們還是需要了解 mysql 的特性的。

  • 如圖我們先在數(shù)據(jù)庫中創(chuàng)建一張?test?表, 表里構(gòu)建一棵樹出來。?祖父→父親→孫子?。

請根據(jù)選中節(jié)點(diǎn)查詢其上游關(guān)系

  • 啥意思呢?就是根據(jù)你我想找到你家血脈關(guān)系。

  • 這個(gè)業(yè)務(wù)本身沒有難點(diǎn),我們只需要一步一步的去尋找即可。但是從技術(shù)層面上看就有點(diǎn)搞頭了。首先我們不確定是多少層,這就無法通過代碼堆砌的方法進(jìn)行實(shí)現(xiàn)了。只能動(dòng)態(tài)的去遞歸查詢。

  • 通過上述代碼我們即可完成家族血脈的查詢。能夠清楚的查出家族的具體支脈。

解析

  • 上面的?sql?雖然能夠?qū)崿F(xiàn)遞歸,但是好像和我們平時(shí)接觸的?sql?不大一樣。這里我們簡單分析下

  • 首先?mysql?是支持我們用戶定義對象的。比如下面這個(gè)?sql

  • 執(zhí)行上面的sql 你會發(fā)現(xiàn)查出來的就是 123 。 這就是使用到 mysql 中變量定義功能。 通過 @ 來進(jìn)行對象的定義以及賦值。


  • 首先 mysql的執(zhí)行順序是由里及外 。 就是說越在內(nèi)部越先執(zhí)行。所以針對上面的 SQL 我們將它整理下順序能夠得出。

  • 注意 (SELECT @r := parent_id FROM test WHERE id = _id) AS parent_id, 這段sql 實(shí)際上歸屬于第二層。圖示中并沒有列出,太占地方了。

第三層

  • 有了上面的兩個(gè)知識點(diǎn)鋪墊,現(xiàn)在我們直接看 SELECT @r := 3, @l := 0 是不是就很容易明白了呢? r、l 就是 mysql 中定義出來的兩個(gè)變量。分別是3,0 。和我們上面演示案列中 select @name from dual 是一個(gè)意思。

  • 至于 (SELECT @r := 3, @l := 0) vars, test AS h這段就更好理解了。test本身就是一張物理表 , 我們定義出來的兩個(gè)變量也可以理解成一張表。在mysql中查詢兩種表是為了區(qū)分開來正常都是需要各自取別名的。所以我們定義的變量就是 vars 別名 。 test 別名 h。

第二層

  • 第二層可以說是遞歸的核心 。這里我們需要明白 上述代碼為什么會產(chǎn)生遞歸的效果呢?首先我們知道?mysql?存在?左外連接、右外連接、內(nèi)連接?。除了這三種還有一種就是?笛卡爾積連接。什么意思呢?

  • 也就是說上面我們的sql?FROM (SELECT @r := 3, @l := 0) vars, test AS h?就是為了給我們構(gòu)建出一個(gè)笛卡爾積 ,而我們定義的變量其實(shí)就是一張表里的一條數(shù)據(jù),所以這里就是將?test?表所有記錄都提取出來。

  • 也就是說我們第二層的sql 就是將 test表全部查出來,然后將其字段進(jìn)行擴(kuò)展。說白了這種方式并不是一種真正的遞歸。但是因?yàn)橐肓艘粋€(gè)變量,所以在擴(kuò)充的時(shí)候和遞歸一個(gè)效果。

  • 但是笛卡爾積查詢出來的數(shù)據(jù)是無法保證兩張表的關(guān)聯(lián)性的,所以我們并沒有將 h 表相關(guān)字段查出來,因?yàn)槟歉緵]用。剩下的就是我們一開始說的一步一步的查詢擴(kuò)充字段了

第一層

  • 第一層就簡單很多了 ,因?yàn)榈诙泳鸵呀?jīng)查詢出來相關(guān)的樹形數(shù)據(jù)了,但是因?yàn)榈诙邮褂玫牡芽柗e h 表信息沒法使用,僅僅使用了其數(shù)量。那么我們的名稱這個(gè)時(shí)候還沒有,第一層的作用就是將節(jié)點(diǎn)名稱擴(kuò)充出來。

總結(jié)

  • 最后我們簡單總結(jié)下,mysql 的查詢遞歸正常使用存儲過程來實(shí)現(xiàn)。但是上面提到的方法巧妙的實(shí)現(xiàn)了遞歸的效果。理論上上述方法和存儲過程相比存在一個(gè)優(yōu)點(diǎn)就是不會死循環(huán)。


mysql巧妙化解遞歸查詢樹形數(shù)據(jù) | 純sql的評論 (共 條)

分享到微博請遵守國家法律
湖口县| 灌云县| 贺兰县| 五河县| 治县。| 中宁县| 巩义市| 额尔古纳市| 奈曼旗| 咸阳市| 达州市| 渭源县| 蒙山县| 商城县| 合水县| 鄂托克旗| 吉隆县| 内江市| 贵南县| 鸡东县| 永昌县| 松江区| 习水县| 武宁县| 咸丰县| 宣恩县| 闽侯县| 保靖县| 皋兰县| 内乡县| 沙湾县| 宜川县| 涟水县| 南充市| 新民市| 错那县| 乐山市| 兴安盟| 元阳县| 枣庄市| 应用必备|