MySQL——复杂的多表查询——以超市交易数据为例
復雜的多表查詢——以超市交易數據為例
之前的內容基本上都是基于單表進行的查詢操作,但是在實際工作中,數據往往分散在多個表中,這個時候我們就需要用到多表查詢的知識了。
通常來說,多表查詢主要有兩類:一類是縱向的表合并,也就是將結構相同的表上下拼接起來;另一類是橫向的表連接,即將多個表中的字段合并到一張大表中。
(1)縱向表合并
縱向表合并非常好理解,就是把多張相同結構的表按照垂直的方向,將它們進行合并,直白的理解就是上下堆疊(也就是記錄的追加)。下面我們以某超市的經營數據為例,來學習一下縱向表合并。
假設有一個大型連鎖超市,它有很多家加盟店,各個加盟店將不同月份的經營數據存儲在各自的數據表中。每家店數據的存儲方式都相同,也就是字段都一樣,分別為:門店ID、用戶ID(如果沒有辦理會員,則用戶ID為空)、訂單ID、交易日期、應付金額、折扣金額、實付金額以及支付類型。
現在的需求是需要把A、B、C三個超市的交易記錄合并到一張表里面。
縱向合并表需要用到UNION或者UNION ALL關鍵詞,這兩個關鍵詞的功能是一樣的(都是合并操作),但是還是有很大區別的:
- UNION ALL 在合并表的時候不做任何附加動作,只是將多個表格簡單的首尾相連;
- UNION 合并表格的時候,除了拼接之外還會多一個附加動作——去重(以前舊版本還有排序功能,新版本舍棄了排序功能)
在性能方面,UNION ALL的合并速度要比UNION 快的多,尤其是數據量比較大的時候,兩者的合并速度差異還是非常明顯的。所以在做縱向表合并的時候,一定要考慮清楚是否需要做去重處理。
# UNION 和 UNION ALL 的區別 SELECT pay_type FROM TransC1805 UNION ALL SELECT pay_type FROM transD1810; SELECT pay_type FROM TransC1805 UNION SELECT pay_type FROM transD1810;下面嘗試使用UNION ALL 將三張交易表合并成一個表:
SELECT * from TransA1710 UNION ALL SELECT * from TransB1801 UNION ALL SELECT * FROM TransC1805;當需要合并的表格的字段數量和順序都一樣的時候,這樣寫是沒有問題的。如果其中有一個表的結構不一致(包括數量和排布順序),這樣寫就會出問題了。比如,現在有超市D在2018年10月份的交易數據,但是這個門店在記錄數據的時候,字段順序做了一些調整:
當要合并的表的字段順序不一致的時候,手動將所有需要的字段都寫出來,并且保證順序一致。
有時候我們并不需要將表中所有記錄和字段都合并,這個時候可以更加靈活使用UNION ALL來完成,比如:將3張表中支付方式為現金(pay_type=1)的交易合并起來,并且保留門店ID、用戶ID、交易訂單號、交易時間和實際交易額信息。
# 將3張表中支付方式為現金(pay_type=1)的交易合并起來,并且保留門店ID、用戶ID、交易訂單號、交易時間和實際交易額信息。 SELECT shop_id,uid,order_id,idate,amt3 from TransA1710 where pay_type=1 UNION ALL SELECT shop_id,uid,order_id,idate,amt3 from TransB1801 where pay_type=1 UNION ALL SELECT shop_id,uid,order_id,idate,amt3 FROM TransC1805 where pay_type=1;(2)表連接操作
關于表連接操作就稍微有點復雜了,這里會用到各種 JOIN操作,對于初學者來說,特別容易搞混,下面我們通過兩個簡單的數據集來學習一下JOIN連接操作:
K=1的記錄在TA和TB兩張表中都有,K=2的記錄為TA表中獨有,K=3的記錄為TB表中獨有。
- 內連接:INNER JOIN
內連接就是把兩張表中共有的數據提取出來。
文氏圖:
- 左連接:LEFT JOIN
左連接查詢會返回左表(TA)中所有記錄,不管右表中有沒有關聯的數據,如果右表中有關聯的數據會被一并返回(右表中沒有的字段,則以NULL值填充)。
文氏圖:
- 右連接:
右連接查詢會返回右表(TB)中所有記錄,不管左表中有沒有關聯的數據,如果左表中有關聯的數
據會被一并返回(左表中沒有的字段,則以NULL值填充)
文氏圖:
- 全連接:FULL OUTER JOIN
FULL OUTER JOIN 一般稱為全連接或者外連接,實際查詢語句中可以寫作 FULL OUTER JOIN 或 FULL JOIN 。外連接查詢能返回左右表里的所有記錄,其中左右表里能關聯起來的記錄被連接后
返回。
文氏圖:
以上就是SQL中常見的四種表連接方式了。此外,還有三種延伸用法,大家感興趣的話,可以自行研究一下。
(3)綜合案例——校園一卡通數據的表連接操作
下面我們通過一個綜合案例來學習一下SQL的表連接操作。這里使用的數據是關于校園一卡通的流水記錄,數據來源于DC競賽網,此數據集共包含兩部分,分別是學生的圖書借閱記錄(共包含239947 條數據)和消費記錄(共包含 條數據)。
- 將數據集導入MySQL中
- 簡單數據探索
數據全部導入MySQL之后,需要對數據進行探索,了解數據現狀:
從返回結果來看,圖書借閱記錄表存在重復記錄,根據實際業務情況,這樣的數據是不應該出現的,所以后續進行數據處理的時候,需要做去重處理。
同樣,對于消費記錄來說,也存在重復值,后續數據處理需要做去重操作,并且,消費金額還有復數,這里我們理解為充值行為(因為負的消費金額會導致余額的增加)。
- 數據處理
由于兩個表中都有重復值,我們首先對數據集進行統計匯總,確保匯總后的結果使得每個學生對應的記錄只有一條。對于學生來說,一般以學年為單位進行分析,所以我們選擇2014年9月——2015年9月作為統計窗口期。
- 表連接操作
將上面處理好的兩張表,整合成一張表。具體選擇何種連接方式,需要根據實際業務需求。
【補充】LOAD DATA的詳細用法
詳細解釋見MySQL用戶手冊《refman-8.0-en.a4.pdf》P2449-P2459
總結
以上是生活随笔為你收集整理的MySQL——复杂的多表查询——以超市交易数据为例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL——单表查询练习:彩票数据核对
- 下一篇: MySQL——多表查询练习:电商数据查询