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

SQL 高級查詢

前面咱們寫了一下 SQL 的極簡入門,今天來講點高級查詢。沒看到的朋友能夠點擊下面連接查看。
1 小時 SQL 極速入門(一)
1 小時 SQL 極速入門(二)
1 小時 SQL 極速入門(三)sql

層次化查詢

層次化結構能夠理解爲樹狀數據結構,由節點構成。好比常見的組織結構由一個總經理,多個副總經理,多個部門部長組成。再好比在生產製造中一件產品會有多個子零件組成。舉個簡單的例子,以下圖所示數據庫

層次圖.png

汽車做爲根節點,下面包含發動機和車身兩個子節點,而子節點又是由其餘葉節點構成。(葉節點表示沒有子節點的節點)數據結構

假如咱們要把這些產品信息存儲到數據庫中,會造成以下數據表。spa

表結構.png

咱們用 parent_product_id 列表示當前產品的父產品是哪個。3d

那麼用 SQL 語句如何進行層次化查詢呢?這裏就要用到 CONNECT BY 和 START WITH 語法。
咱們先把 SQL 寫出來,再來解釋其中的含義。code

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

查詢結果以下:blog

查詢1.png

解釋一下:LEVEL 列表示當前產品屬於第幾層級。START WITH 表示從哪個產品開始查詢,CONNECT BY PRIOR 表示父節點與子節點的關係,每個產品的 ID 指向一個父產品。遞歸

若是咱們把 START WITH 的查詢起點改成 id = 2,從新運行上面的 SQL 語句將會獲得以下結果:get

查詢2.png

由於 id=2 的產品是車身,咱們就只能查到車身下面的子產品。產品

固然,咱們能夠把查詢結果美化一下,使其更有層次感,咱們讓根節點下面的 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

查詢結果已經有了層次感,以下圖:

圖三.png

遞歸查詢

除了使用上面咱們說的方法,還能夠使用遞歸查詢獲得一樣的結果。遞歸會用到 WITH 語句。普通的 WITH 語句能夠看做一個子查詢,咱們在 WITH 外部能夠直接使用這個子查詢的內容。

當遞歸查詢時,咱們是在 WITH 語句內部來引用這個子查詢。仍是上面的例子,咱們使用 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 語句咱們查詢出來了根節點,而且設置爲 level = 0,第二條SELECT 語句關聯上 WITH 語句自身,而且 level 每層加 1 進行遞歸。

查詢結果以下:

WITH.png

能夠看到第一列是展現的產品層級,和咱們上面查詢出來的結果是一致的。

同時使用 WITH 遞歸時還能夠使用深度優先搜索和廣度優先搜索,什麼意思呢?廣度優先就是在返回子行以前首先返回兄弟行,如上圖,首先把車身和發動機兩個兄弟行返回,以後是他們下面的子行。相反,深度優先就是首先返回一個父節點的子行再返回另外一個兄弟行。

咱們只須要在 SELECT 語句上方加上下面語句便可實現深度優先搜索查詢。

search depth FIRST BY id
  SET order_by_id

結果以下,看到首先返回每一個父節點下的子行,再返回另外一個父節點。

深度優先.png

同理,廣度優先使用的是下面的 SQL 語句

search breadth FIRST BY id
  SET order_by_id
相關文章
相關標籤/搜索