成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

SQL高級查詢(層次化查詢,遞歸)

young.li / 771人閱讀

摘要:高級查詢前面我們寫了一下的極簡入門,今天來說點(diǎn)高級查詢。查詢結(jié)果已經(jīng)有了層次感,如下圖遞歸查詢除了使用上面我們說的方法,還可以使用遞歸查詢得到同樣的結(jié)果。當(dāng)遞歸查詢時(shí),我們是在語句內(nèi)部來引用這個子查詢。

SQL 高級查詢

前面我們寫了一下 SQL 的極簡入門,今天來說點(diǎn)高級查詢。沒看到的朋友可以點(diǎn)擊下面鏈接查看。
1 小時(shí) SQL 極速入門(一)
1 小時(shí) SQL 極速入門(二)
1 小時(shí) SQL 極速入門(三)

層次化查詢

層次化結(jié)構(gòu)可以理解為樹狀數(shù)據(jù)結(jié)構(gòu),由節(jié)點(diǎn)構(gòu)成。比如常見的組織結(jié)構(gòu)由一個總經(jīng)理,多個副總經(jīng)理,多個部門部長組成。再比如在生產(chǎn)制造中一件產(chǎn)品會有多個子零件組成。舉個簡單的例子,如下圖所示

汽車作為根節(jié)點(diǎn),下面包含發(fā)動機(jī)和車身兩個子節(jié)點(diǎn),而子節(jié)點(diǎn)又是由其他葉節(jié)點(diǎn)構(gòu)成。(葉節(jié)點(diǎn)表示沒有子節(jié)點(diǎn)的節(jié)點(diǎn))

假如我們要把這些產(chǎn)品信息存儲到數(shù)據(jù)庫中,會形成如下數(shù)據(jù)表。

我們用 parent_product_id 列表示當(dāng)前產(chǎn)品的父產(chǎn)品是哪一個。

那么用 SQL 語句如何進(jìn)行層次化查詢呢?這里就要用到 CONNECT BY 和 START WITH 語法。
我們先把 SQL 寫出來,再來解釋其中的含義。

SELECT
  level,
  id,
  parent_product_id,
  name
FROM
  product
  START WITH id  = 1
  CONNECT BY prior id = parent_product_id
ORDER BY
  level

查詢結(jié)果如下:

解釋一下:LEVEL 列表示當(dāng)前產(chǎn)品屬于第幾層級。START WITH 表示從哪一個產(chǎn)品開始查詢,CONNECT BY PRIOR 表示父節(jié)點(diǎn)與子節(jié)點(diǎn)的關(guān)系,每一個產(chǎn)品的 ID 指向一個父產(chǎn)品。

如果我們把 START WITH 的查詢起點(diǎn)改為 id = 2,重新運(yùn)行上面的 SQL 語句將會得到如下結(jié)果:

因?yàn)?id=2 的產(chǎn)品是車身,我們就只能查到車身下面的子產(chǎn)品。

當(dāng)然,我們可以把查詢結(jié)果美化一下,使其更有層次感,我們讓根節(jié)點(diǎn)下面的 LEVEL 前面加幾個空格即可。把上面的 SQL 稍微修改一下。為每個 LEVEL 前面增加 2*(LEVEL-1)個空格,這樣第二層就會增加兩個空格,第三層會增加四個空格。

SELECT
  level,
  id,
  parent_product_id,
  LPAD(" ", 2 * (level - 1)) || name AS name
FROM
  product
  START WITH id  = 1
  CONNECT BY prior id = parent_product_id

查詢結(jié)果已經(jīng)有了層次感,如下圖:

遞歸查詢

除了使用上面我們說的方法,還可以使用遞歸查詢得到同樣的結(jié)果。遞歸會用到 WITH 語句。普通的 WITH 語句可以看作一個子查詢,我們在 WITH 外部可以直接使用這個子查詢的內(nèi)容。

當(dāng)遞歸查詢時(shí),我們是在 WITH 語句內(nèi)部來引用這個子查詢。還是上面的例子,我們使用 WITH 語句來查詢。

WITH
  temp_product (product_level, id, parent_product_id,name) AS
  (
    SELECT
      0 AS product_level,id,parent_product_id,name
    FROM
      product
    WHERE
      parent_product_id IS NULL
    UNION ALL
    SELECT
      tp.product_level + 1,p.id,
      p.parent_product_id,
      p.name
    FROM
      product p
    JOIN temp_product tp
    ON
      p.parent_product_id=tp.id
  )
SELECT
  product_level,
  id,
  parent_product_id,
  LPAD(" ", 2 * product_level)
  || name AS NAME
FROM
  temp_product;

第一條 SELECT 語句我們查詢出來了根節(jié)點(diǎn),并且設(shè)置為 level = 0,第二條SELECT 語句關(guān)聯(lián)上 WITH 語句自身,并且 level 每層加 1 進(jìn)行遞歸。

查詢結(jié)果如下:

可以看到第一列是展示的產(chǎn)品層級,和我們上面查詢出來的結(jié)果是一致的。

同時(shí)使用 WITH 遞歸時(shí)還可以使用深度優(yōu)先搜索和廣度優(yōu)先搜索,什么意思呢?廣度優(yōu)先就是在返回子行之前首先返回兄弟行,如上圖,首先把車身和發(fā)動機(jī)兩個兄弟行返回,之后是他們下面的子行。相反,深度優(yōu)先就是首先返回一個父節(jié)點(diǎn)的子行再返回另一個兄弟行。

我們只需要在 SELECT 語句上方加上下面語句即可實(shí)現(xiàn)深度優(yōu)先搜索查詢。

  search depth FIRST BY id
  SET order_by_id

結(jié)果如下,看到首先返回每個父節(jié)點(diǎn)下的子行,再返回另一個父節(jié)點(diǎn)。

同理,廣度優(yōu)先使用的是下面的 SQL 語句

  search breadth FIRST BY id
  SET order_by_id

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/17907.html

相關(guān)文章

  • GROUP BY你都不會!ROLLUP,CUBE,GROUPPING詳解

    摘要:當(dāng)向傳入一列時(shí),會得到一個總計(jì)行。結(jié)果當(dāng)向傳遞兩列時(shí),將會按照這兩列進(jìn)行分組,同時(shí)按照第一列的分組結(jié)果返回小計(jì)行。結(jié)果可以看出來結(jié)果是按照工廠和部門分別分組匯總的。選擇的就表示兩列都不為空。 Group By Group By 誰不會???這不是最簡單的嗎?越是簡單的東西,我們越會忽略掉他,因?yàn)槲覀儾辉敢庠偃ド钊肓私馑? 小時(shí) SQL 極速入門(一)1 小時(shí) SQL 極速入門(二)1 ...

    only_do 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<