1.SQL不是用來生成報表的語言,所以不建議用它來進行格式轉換;
2.必要時考慮用外連接或者CASE表達式來解決問題;
3.生成嵌套式表側欄時,如果先生成主表的笛卡爾積再進行連接,很容易就可以完成;
4.從行數來看,表連接可以看成乘法。因此,當表之間是一對多的關係時,連接後行數不會增加;
5.外連接的思想和集合運算很像,使用外連接可以實現各種集合運算。
練習題
1.先連接還是先聚合
在“交叉表裏製作嵌套式表側欄”部分裏,我們通過聚合將DATA視圖和MASTER視圖轉換為一對一的關係之後進行了連接操作。採用這種做法時,代碼的確比較好理解,但是這就需要創建兩個臨時視圖,性能並不是很好。請想辦法改善一下代碼,儘量減少臨時視圖。
SELECT MASTER.age_range AS '年齡層級',
MASTER.sex AS '性別',
SUM(CASE WHEN pref_name IN ('秋田','青森') THEN population ELSE NULL END) AS pop_tohoku,
SUM(CASE WHEN pref_name IN ('東京','千葉') THEN population ELSE NULL END) AS pop_kanto
FROM (SELECT age_class, age_range, sex, sex_cd
FROM TblAge CROSS JOIN TblSex ) MASTER
LEFT JOIN tblpop
ON MASTER.age_class = tblpop.age_class AND MASTER.sex_cd = tblpop.sex_cd
GROUP BY age_range, sex
UNION
SELECT MASTER.age_range AS '年齡層級',
MASTER.sex AS '性別',
SUM(CASE WHEN pref_name IN ('秋田','青森') THEN population ELSE NULL END) AS pop_tohoku,
SUM(CASE WHEN pref_name IN ('東京','千葉') THEN population ELSE NULL END) AS pop_kanto
FROM (SELECT age_class, age_range, sex, sex_cd
FROM TblAge CROSS JOIN TblSex ) MASTER
RIGHT JOIN tblpop
ON MASTER.age_class = tblpop.age_class AND MASTER.sex_cd = tblpop.sex_cd
GROUP BY age_range, sex
原方法是這樣的:
SELECT MASTER.age_range AS '年齡層級',
MASTER.sex AS '性別',
DATA.pop_tohoku AS '東北',
DATA.pop_kanto AS '關東'
FROM (SELECT age_class, age_range, sex, sex_cd
FROM TblAge CROSS JOIN TblSex ) MASTER
LEFT JOIN (SELECT age_class, sex_cd,
SUM(CASE WHEN pref_name IN ('秋田','青森') THEN population ELSE NULL END) AS pop_tohoku,
SUM(CASE WHEN pref_name IN ('東京','千葉') THEN population ELSE NULL END) AS pop_kanto
FROM tblpop
GROUP BY age_class, sex_cd) DATA
ON MASTER.age_class = DATA.age_class AND MASTER.sex_cd = DATA.sex_cd;
視圖MASTER 和DATA中行的關係時一對一的關係:
MASTER
DATA
而實際上MASTER與 tblpop表中的內容是一對多的關係,按照本節中:表連接可以看成行的乘法的觀點,可以直接將master與tblpop進行全外連接:
由於Mysql不支持 FULL OUTER JOIN,所以採用 左外連接 union 右外連接的方法進行拼接。
在本題中我將先聚合後連接改成了先連接後聚合,到底應該先採用哪種方法呢?
二、請留意孩子的人數
在“用外連接進行行列轉換(列—>行):彙總重複列於一列”部分,我們求得了以員工為單位的員工子女列表。有了這幾個列表之後,對員工進行一下聚合很容易就可以知道每個員工撫養了幾個孩子。
期待輸出的結果如下所示:
SELECT EMP.employee, COUNT(CHILDREN.child) AS child_cnt
FROM personnel EMP LEFT JOIN CHILDREN
ON CHILDREN.child IN (EMP.child_1, EMP.child_2, EMP.child_3)
GROUP BY employee
ORDER BY child_cnt DESC
三、全外連接和MERGE運算符
MERGE運算符是在SQL:2003標準中引入的新特性,因為它可以將兩張表的信息彙總到一張表上,所以在需要將分散在多個數據源的數據彙總到一起的場景中能發揮很強大的威力。
使用如下兩張表:
現在需要將class_b中的數據彙總到class_a裏。處理邏輯是在表Class_A中查詢表Class_B裏的“id”列,如果存在則更新名字,如果不存在則插入。因此,兩張表中同名的1號“田中”,以及表Class_B中不存在的3號“伊集院”沒有變化,兩張表中編號相同名字卻不同的2號“鈴木”被更新成“內海”,表Class_A中不存在的新同學“西園寺”被添加進表中。
MERGE INTO 的用法,MySQL中沒有MERGE_INTO可以使用:
MERGE語句主要分為三塊,第一塊指定合併的表和匹配的列,即代碼中的A快,ON(A.id = B.id)是匹配條件。
然後對每條記錄進行匹配,並根據是否匹配到進行分支處理,本例中,對匹配到的記錄執行 update語句,對沒有匹配到的記錄執行INSERT語句,執行結果之後會得到 A+B這樣存儲了完整信息的表。
在MySQL中如何實現??