1 小時 SQL 極速入門(二)

李英傑同學發表於2018-12-03

eeee.jpg

上篇我們說了 SQL 的基本語法,掌握了這些基本語法後,我們可以對單表進行查詢及計算分析。但是一個大的系統,往往會有數十上百張表,而業務關係又錯綜複雜。我們要查的資料往往在好幾張表中,而要從多張表中來獲取資訊就需要用到表聯結了。

先說說什麼是聯結,聯結就是用一條 SELECT 語句從多個表中查詢資料。通過聯結,讓多張表中的資料互相關聯起來。聯結又分為內聯結、左外聯結、右外聯結、全外聯結。別怕,我知道有些初學者看到這幾個概念就頭大,不過請繼續往後看,看完後你肯定能看明白。在實際中,內聯結和左聯結應該是使用最多的,我幾乎沒用到過右連線與全外聯結。

對初學者來說,在這裡迷惑的原因是去記這些概念,這是沒必要的,我們只要在實際中抱著問題去用一次就可以完全掌握了。

下面我們就開始:
我們有下面三張表,一張訂單表存放訂單頭資訊,包括訂單號、訂單型別、訂單數量、訂單狀態資訊。
ORDER_HEADER.png

一張訂單明細表,儲存訂單的詳細資訊。包含訂單號、訂單型別、工序號、工序名稱、工序狀態、物料號、工位號

ORDER_DETAIL.png

一張物料表,儲存訂單工序用到的物料。包含物料號、物料名稱。

PRODUCT.png

內聯結

我們先觀察一下,訂單頭資訊中只包含訂單的數量、狀態資訊。訂單明細表中包含著訂單的詳細資訊,如工序資訊,每道工序用到的物料,每道工序的名稱,在哪個工位操作等資訊。假如我們現在要查詢訂單號、訂單數量、工序號、工序名稱、工位等資訊,只有一張表我們是查不到的,那麼我們就要把這兩張表結合起來。

SELECT
  oh.orderno,
  oh.order_type,
  oh.quantity,
  od.order_line_no,
  od.order_line_name,
  od.workcenter
FROM
  order_header oh
INNER JOIN order_detail od
ON
  oh.orderno     =od.orderno
AND oh.order_type=od.order_type

解釋下:我們用INNER JOIN 表示內連線,在 INNER JOIN 後寫上我們需要關聯的表,oh 和 od 表示別名,方便後面書寫,不然後面我們就要用到表的全稱來寫了。這裡我們要關聯到訂單明細表 order_detail,去取出訂單詳細資訊。後面跟上 ON 關鍵字,表示條件,這裡 ON 後面有兩個條件。表示我們通過訂單號和訂單型別來把兩個表中的資料關聯起來,通過訂單表中的訂單號和訂單型別作為條件來查詢訂單明細表中同樣訂單號和訂單型別的訂單的詳細資訊。

我們看下結果:

JOIN1.png

可以看到,我們查出了訂單 1001 ,1002, 1003, 1004, 1005五個訂單的總數量,各個工序的名稱,在哪個工位生產等資訊。

細心的讀者可能會注意到,在訂單表中還有一個 1008 的訂單,為什麼沒有查出來?那就接著往下看

左聯結

相比於內聯結,左聯結使用 LEFT JOIN 來表示。我們先不看概念,我們直接把剛才的 SQL 語句改成左聯結來看一下結果。

SELECT
  oh.orderno,
  oh.order_type,
  oh.quantity,
  od.order_line_no,
  od.order_line_name,
  od.workcenter
FROM
  order_header oh
LEFT JOIN order_detail od
ON
  oh.orderno     =od.orderno
AND oh.order_type=od.order_type;

結果如下圖:

LEFTJOIN.png

對比內聯結的結果,我們發現了什麼,我們發現最下面多了一行,1008 訂單,而1008 後面的幾個欄位為空。我們看一下訂單明細表會發現沒有 1008 這個訂單。

這樣子我們就明白了,內聯結是兩張表中都存在才能關聯出來。而左聯結的意思就是我們的主表中的所有行都會展示出來,如果在聯結的表中找不到對應的,會預設為 null.

右聯結

知道了左聯結,右聯結也就清楚了,右連線呢會把我們關聯的表中的所有行都展示出來,不管主表中有沒有匹配的行。右聯結關鍵字為 RIGHT JOIN

SELECT
  oh.orderno,
  oh.order_type,
  oh.quantity,
  od.order_line_no,
  od.workcenter
FROM
  order_header oh
RIGHT JOIN order_detail od
ON
  oh.orderno     =od.orderno
AND oh.order_type=od.order_type;

RIGHTJOIN.png

可以看到,RIGHT JOIN 把關聯的訂單明細表中的所有行都顯示了出來,但是訂單主表中並沒有 1006 和 1007 兩個訂單,所以這兩行顯示為 null

多表聯結

多表聯結就是超過兩張表的聯結,上面我們關聯了訂單表和訂單明細表,現在我們想知道每道工序用到的物料,就需要關聯到物料表。我們看到訂單明細表中有 productid 欄位,我們用這個關聯到 product 表中。同時,後面我們也用了 ORDER BY 進行排序。

SELECT
  oh.orderno,
  oh.order_type,
  oh.quantity,
  od.order_line_no,
  od.workcenter,
  p.productno,
  p.product_name
FROM
  order_header oh
INNER JOIN order_detail od
ON
  oh.orderno =od.orderno
INNER JOIN product1 p
ON
  od.productid   =p.ID
AND oh.order_type=od.order_type
ORDER BY
  orderno,
  order_line_no

JOIN2.png

注意

在使用聯結時一定要注意聯結條件,如果 聯結條件不正確,就會得到不正確的結果。而且要注意,聯結條件是必須的。

UNION 與 UNION ALL

UNION 與 UNION ALL 表示並集,可以把兩個 SELECT 查詢的結果合併成一個,前提是兩個 SELECT 所查詢的列數量和欄位型別一致。不同的是 UNION 會去除重複行,而 UNION ALL 不會去除重複行。

如果我們有兩張表,都存有相似的資訊。比如我們在一個其他表中也儲存的有訂單資訊。舉個例子,order_header_bak 表中存有如下兩條資料。
ORDERBAK.png

我們用 UNION ALL 試一下

SELECT
  orderno,
  order_type,
  order_status
FROM
  order_header
UNION ALL
SELECT
  orderno,
  order_type,
  order_status
FROM
  order_header_bak;

UNIONALL.png

看到查出了 8 條資訊,1001 訂單有兩條一樣的資訊。
我們用 UNION 試一下

SELECT
  orderno,
  order_type,
  order_status
FROM
  order_header
UNION
SELECT
  orderno,
  order_type,
  order_status
FROM
  order_header_bak

UNION.png

看到只有 7 條資料了, 1001 訂單隻有一行資料。

相關文章