日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sql三个表join_「数据蒋堂」第 31 期:JOIN 简化 – 维度对齐

發(fā)布時間:2023/12/9 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sql三个表join_「数据蒋堂」第 31 期:JOIN 简化 – 维度对齐 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【數(shù)據(jù)蔣堂】第 31 期:JOIN 簡化 – 維度對齊

我們先把上一期中雙子表對齊例子的 SQL 寫出來:

SELECT Orders.id, Orders.customer, A.x, B.y FROM Orders LEFT JOIN (SELECT id,SUM(price) x FROM OrderDetail GROUP BY id ) A ON Orders.id=A.id LEFT JOIN (SELECT id,SUM(amount) y FROM OrderPayment GROUP BY id ) B ON Orders.id=B.id WHERE A.x > B.y SELECT Orders.id, Orders.customer, A.x, B.y FROM Orders LEFT JOIN (SELECT id,SUM(price) x FROM OrderDetail GROUP BY id ) A ON Orders.id=A.id LEFT JOIN (SELECT id,SUM(amount) y FROM OrderPayment GROUP BY id ) B ON Orders.id=B.id WHERE A.x > B.y

那么問題來了,這顯然是個有業(yè)務(wù)意義的 JOIN,它算是前面所說的哪一類呢?

這個 JOIN 涉及了表 Orders 和子查詢 A 與 B,仔細觀察會發(fā)現(xiàn),子查詢帶有 GROUP BY id 的子句,顯然,其結(jié)果集將以 id 為主鍵。這樣,JOIN 涉及的三個表(子查詢也算作是個臨時表)的主鍵是相同的,它們是一對一的同維表,仍然在前述的范圍內(nèi)。

但是,這個同維表 JOIN 卻不能用上一期說的寫法簡化,子查詢 A,B 都不能省略不寫。

可以簡化書寫的原因在于:我們假定事先知道數(shù)據(jù)結(jié)構(gòu)中這些表之關(guān)聯(lián)關(guān)系。用技術(shù)術(shù)語的說法,就是知道數(shù)據(jù)庫的元數(shù)據(jù)(metadata)。而對于臨時產(chǎn)生的子查詢,顯然不可能事先定義在元數(shù)據(jù)中了,這時候就必須明確指定要 JOIN 的表(子查詢)。

不過,雖然 JOIN 的表不能省略,但關(guān)聯(lián)字段總是主鍵,已經(jīng)在 GROUP BY 中寫過了,就沒有必要再寫一遍了;而且,子查詢的主鍵總是由 GROUP 產(chǎn)生,而 GROUP BY 的字段一定要被選出用于做外層 JOIN,也沒必要在 GROUP 和 SELECT 中各寫一次;并且這幾個子查詢涉及的子表是互相獨立的,它們之間不會再有關(guān)聯(lián)計算了,我們就可以把 GROUP 動作以及聚合式直接放到主句中,從而消除一層子查詢:

SELECT Orders.id, Orders.customer, OrderDetail.SUM(price) x, OrderParyment.SUM(amount) y FROM Orders LEFT JOIN OrderDetail GROUP BY id LEFT JOIN OrderPayment GROUP BY id WHERE A.x > B.y SELECT Orders.id, Orders.customer, OrderDetail.SUM(price) x, OrderParyment.SUM(amount) y FROM Orders LEFT JOIN OrderDetail GROUP BY id LEFT JOIN OrderPayment GROUP BY id WHERE A.x > B.y

這里的 JOIN 和 SQL 定義的 JOIN 運算已經(jīng)差別很大,完全沒有笛卡爾積的意思了。而且,也不同于 SQL 的 JOIN 運算將定義在任何兩個表之間,這里的 JOIN,OrderDetail 和 OrderPayment 以及 Orders 都是向共同的主鍵 id 靠攏,即所有表都向某一套基準維度對齊。而由于各表的維度(主鍵)不同,對齊時可能會有 GROUP BY,在引用該表字段時就會相應(yīng)地出現(xiàn)聚合運算。OrderDetail 和 OrderPayment 甚至 Orders 之間都不直接發(fā)生關(guān)聯(lián),在書寫運算時當然就不用關(guān)心它們之間的關(guān)系,甚至不必關(guān)心另一個表是否存在。而 SQL 那種笛卡爾積式的 JOIN 則總要找一個甚至多個表來定義關(guān)聯(lián),一旦減少或修改表時就要同時考慮關(guān)聯(lián)表,增大理解難度。

我們稱這種 JOIN 稱為維度對齊,它并不超出我們前面說過的三種 JOIN 范圍,但確實在語法描述上會有不同,這里的 JOIN 不象 SQL 中是個動詞,卻更象個連詞。而且,和前面三種基本 JOIN 中不會或很少發(fā)生 FULL JOIN 的情況不同,維度對齊的場景下 FULL JOIN 并不是很罕見的情況。

雖然我們從主子表的例子抽象出維度對齊,但這種 JOIN 并不要求 JOIN 的表是主子表(事實上從上一篇的語法可知,主子表運算還不用寫這么麻煩),任何多個表都可以這么關(guān)聯(lián),而且關(guān)聯(lián)字段也完全不必要是主鍵或主鍵的部分。

設(shè)有合同表,回款表和發(fā)票表:

Contract 合同表

id合同編號date簽訂日期customer客戶price合同金額……

Payment 回款表

seq回款序號date回款日期source回款來源amount金額……

Invoice 發(fā)票表

code 發(fā)票編號

date 開票日期

customer 客戶

amount 開票金額

現(xiàn)在想統(tǒng)計每一天的合同額、回款額以及發(fā)票額,就可以寫成:

SELECT Contract.SUM(price), Payment.SUM(amount), Invoice.SUM(amount) FROM Contract GROUP BY date FULL JOIN Payment GROUP BY date FULL JOIN Invoice GROUP BY date SELECT Contract.SUM(price), Payment.SUM(amount), Invoice.SUM(amount) FROM Contract GROUP BY date FULL JOIN Payment GROUP BY date FULL JOIN Invoice GROUP BY date

這幾種 JOIN 情況還可能混合出現(xiàn)。

延用上面的合同表,再有客戶表和銷售員表

Customer 客戶表

|—|—|

|id| 客戶編號 |

|name| 客戶名稱 |

|area| 所在地區(qū) |

|…|…|

Sales 銷售員表

id員工編號name姓名area負責地區(qū)……

其中 Contract 表中 customer 字段是指向 Customer 表的外鍵。

現(xiàn)在我們想統(tǒng)計每個地區(qū)的銷售員數(shù)量及合同額:

SELECT Sales.COUNT(1), Contract.SUM(price) FROM Sales GROUP BY area FULL JOIN Contract GROUP BY customer.area SELECT Sales.COUNT(1), Contract.SUM(price) FROM Sales GROUP BY area FULL JOIN Contract GROUP BY customer.area

維度對齊可以和外鍵屬性化的寫法配合合作。

這些例子中,最終的 JOIN 都是同維表。事實上,維度對齊還有主子表對齊的情況,不過相對罕見,我們將在后續(xù)仔細講解維度概念時再涉及,上述寫法中其實還有個小漏洞,有了明確的維度定義后才能將這個漏洞補上。

總結(jié)

以上是生活随笔為你收集整理的sql三个表join_「数据蒋堂」第 31 期:JOIN 简化 – 维度对齐的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。