同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總

前端小梅子 2021-09-20 03:45:15 阅读数:430

同事 mysql 逼了 nginx
  • [最全面試題新鮮出爐:70+算法題、近30種大廠面試筆試常考知識點](

)

前言

最近在做的業務場景涉及到了數據庫的遞歸查詢。我們公司用的 Oracle ,眾所周知,Oracle 自帶有遞歸查詢的功能,所以實現起來特別簡單。

但是,我記得 MySQL 是沒有遞歸查詢功能的,那 MySQL 中應該怎麼實現呢?

於是,就有了這篇文章。

文章主要知識點:

  • Oracle 遞歸查詢, start with connect by prior 用法
  • find_in_set 函數
  • concat,concat_ws,group_concat 函數
  • MySQL 自定義函數
  • 手動實現 MySQL 遞歸查詢

Oracle 遞歸查詢

在 Oracle 中是通過 start with connect by prior 語法來實現遞歸查詢的。

按照 prior 關鍵字在子節點端還是父節點端,以及是否包含當前查詢的節點,共分為四種情况。

prior 在子節點端(向下遞歸)

第一種情况: start with 子節點id = ’ 查詢節點 ’ connect by prior 子節點id = 父節點id

select * from dept start with id='1001' connet by prior id=pid;

  • 1.

這裏,按照條件 id=‘1001’ 對當前節點以及它的子節點遞歸查詢。查詢結果包含自己及所有子節點。

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_後端

第二種情况: start with 父節點id= ’ 查詢節點 ’ connect by prior 子節點id = 父節點 id

select * from dept start with pid='1001' connect by prior id=pid;

  • 1.

這裏,按照條件 pid=‘1001’ 對當前節點的所有子節點遞歸查詢。查詢結果只包含它的所有子節點,不包含自己

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_Java_02

其實想一想也對,因為開始條件是以父節點為根節點,且向下遞歸,自然不包含當前節點。

prior 在父節點端(向上遞歸)

第三種情况: start with 子節點id= ’ 查詢節點 ’ connect by prior 父節點id = 子節點id

select * from dept start with id='1001' connect by prior pid=id;

  • 1.
  • 2.

這裏按照條件 id=‘1001’ ,對當前節點及其父節點遞歸查詢。查詢結果包括自己及其所有父節點。

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_程序員_03

第四種情况: start with 父節點id= ’ 查詢節點 ’ connect by prior 父節點id = 子節點id

select * from dept start with pid='1001' connect by prior pid=id;

  • 1.

這裏按照條件 pid=‘1001’,對當前節點的第一代子節點以及它的父節點遞歸查詢。查詢結果包括自己的第一代子節點以及所有父節點。(包括自己

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_Java_04

其實這種情况也好理解,因為查詢開始條件是以?父節點為根節點,且向上遞歸,自然需要把當前父節點的第一層子節點包括在內。

以上四種情况初看可能會讓人迷惑,容易記混亂,其實不然。

我們只需要記住?prior 的比特置在子節點端,就向下遞歸,在父節點端就向上遞歸。

  • 開始條件若是子節點的話,自然包括它本身的節點。
  • 開始條件若是父節點的話,則向下遞歸時,自然不包括當前節點。而向上遞歸,需要包括當前節點及其第一代子節點。

MySQL 遞歸查詢

可以看到,Oracle 實現遞歸查詢非常的方便。但是,在 MySQL 中並沒有幫我們處理,因此需要我們自己手動實現遞歸查詢。

為了方便,我們創建一個部門錶,並插入幾條可以形成遞歸關系的數據。

DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`id` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`pid` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1000', '總公司', NULL);
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1001', '北京分公司', '1000');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1002', '上海分公司', '1000');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1003', '北京研發部', '1001');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1004', '北京財務部', '1001');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1005', '北京市場部', '1001');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1006', '北京研發一部', '1003');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1007', '北京研發二部', '1003');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1008', '北京研發一部一小組', '1006');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1009', '北京研發一部二小組', '1006');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1010', '北京研發二部一小組', '1007');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1011', '北京研發二部二小組', '1007');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1012', '北京市場一部', '1005');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1013', '上海研發部', '1002');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1014', '上海研發一部', '1013');
INSERT INTO `dept`(`id`, `name`, `pid`) VALUES ('1015', '上海研發二部', '1013');

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

沒錯,剛才 Oracle 遞歸,就是用的這張錶。

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_後端_05

另外,在這之前,我們需要複習一下幾個 MYSQL中的函數,後續會用到。

find_in_set 函數

函數語法:find_in_set(str,strlist)

str 代錶要查詢的字符串 , strlist 是一個以逗號分隔的字符串,如 (‘a,b,c’)。

此函數用於查找 str 字符串在字符串 strlist 中的比特置,返回結果為 1 ~ n 。若沒有找到,則返回0。

舉個栗子:

select FIND_IN_SET('b','a,b,c,d');

  • 1.

結果返回 2 。因為 b 所在比特置為第二個子串比特置。

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_後端_06

此外,在對錶數據進行查詢時,它還有一種用法,如下:

select * from dept where FIND_IN_SET(id,'1000,1001,1002');

  • 1.

結果返回所有 id 在 strlist 中的記錄,即 id = ‘1000’ ,id = ‘1001’ ,id = ‘1002’ 三條記錄。

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_程序員_07

看到這,對於我們要解决的遞歸查詢,不知道你有什麼啟發沒。

以向下遞歸查詢所有子節點為例。我想,是不是可以找到一個包含當前節點和所有子節點的以逗號拼接的字符串 strlist,傳進 find_in_set 函數。就可以查詢出所有需要的遞歸數據了。

那麼,現在問題就轉化為怎樣構造這樣的一個字符串 strlist 。

這就需要用到以下字符串拼接函數了。

concat,concat_ws,group_concat 函數

一、字符串拼接函數中,最基本的就是 concat 了。它用於連接N個字符串,如,

select CONCAT('M','Y','S','Q','L') from dual;

  • 1.

最後總結

ActiveMQ+Kafka+RabbitMQ學習筆記PDF

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_程序員_08

  • RabbitMQ實戰指南

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_Java_09

  • 手寫RocketMQ筆記

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_程序員_10

  • 手寫“Kafka筆記”

同事問我MySQL怎麼遞歸查詢,我懵逼了,nginx面試題匯總_程序員_11

關於分布式,限流+緩存+緩存,這三大技術(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。這些相關的面試也好,還有手寫以及學習的筆記PDF,都是啃透分布式技術必不可少的寶藏。以上的每一個專題每一個小分類都有相關的介紹,並且小編也已經將其整理成PDF啦

 CodeChina開源項目:【一線大廠Java面試題解析+核心總結學習筆記+最新講解視頻】

版权声明:本文为[前端小梅子]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210920034514924a.html