SQL 以面向集合的思維方式來思考

2021-06-01 08:36:50 字數 2626 閱讀 2488

圖4-1給出了12張卡片,從中你應該可以找出6個集合。每張卡片左上角的字母表示顏色(r=紅色,g=綠色,p=紫色)。試試吧。

答案在本章的最後(可別作弊哦!)。我首先給出第乙個集合:第1行第2列(實心綠色花體),第3行第2列(實心紅色花體)和第3行第4列(實心紫色花體)。這個遊戲迫使你按集合來思考,除此以外別無他法。如果你覺得找出集合很困難,我打賭你在寫sql語句的時候就會覺得以面向集合的方式來思考更困難。sql語句的書寫工作與這個遊戲是具有同樣的前提的(必須要有面向集合的思維方式!),只不過是另外乙個不同的遊戲罷了。既然你已經在面向集合的思考方面熱過身了,讓我們來看看從面向過程的思維方式轉變到面向集合的思維方式的幾種方法。

從面向過程轉變為基於集合的思維方式

你首先需要做的是停止那些一次處理一行資料的過程化步驟思維。如果你一次只想處理一行,實現你的想法將會使用短語如「for each row do x」或者 「while value is y do x」。試著把思路轉移到使用類似於「for all」的短語上來。有關於此的乙個簡單的例子就是加數字。當你按過程化來考慮的時候,你就會想把一行的數值與另一行的數值加起來直到把所有行加到一起。對所有行求和的思維與此不同。正如我所說的,這是個非常簡單的例子,但類似的思維方式的轉變同樣適用於更複雜的不是那麼明顯的情況下。

例如,如果我讓你生成乙個所有在公司裡每個工作崗位上幹了同樣年數的員工列表,你會怎麼做?如果你按照過程化的思維方式來進行,你可能需要去檢視每個工作崗位,計算出在這個崗位上的工作年限,然後與在其他各個崗位的工作年限比較。如果年數不匹配,那麼你就不會把這個員工放到結果列表中。這種方法將會通過如下的乙個自聯結的查詢來進行:

相反,如果你使用面向集合的觀點來看待這個問題,你就會寫出對錶只進行一次訪問的查詢,按照員工進行分組,然後篩選出那些在某個崗位上工作的最短年數與某個崗位上工作的最長年數相一致的員工。

**清單4-1分別列出了這兩種選擇的執行過程。你可以看到基於集合的方法使用了較少的邏輯讀取並擁有更簡潔的計畫。

**清單4-

1過程化與基於集合的方法的對比

關鍵是要開始以完成後的結果的形式(而不是以處理步驟的形式)來思考。要找集合的特徵而不是單獨的步驟或行為。在基於集合的思維方式中,所有事物都以應用於集合的篩選條件或約束所定義的狀態存在。你不再按照過程步驟來思考而是要按照集合的狀態來思考。圖4-2給出了處理步驟圖與巢狀集合圖之間的乙個比較用來說明我的觀點。

處理流程圖表明結果集(a)是通過一系列以其他步驟為基礎的處理步驟來產生的最終答案。b通過遍歷c和d得出,然後a通過遍歷b和e得出。但是,巢狀集合圖中將a看做是不同集合的組合的結果。

另一種常見的但卻是錯誤的思考方式就是將表看做是排過序的行的集合。想想你所看到的典型的表的內容。它們是在乙個**或者類似於工作表的檢視中展示出來的。但是,一張表代表乙個集合,集合是無序的。通過表明一定順序的方法來展示表可能會引起混淆。回憶一下在第2章中order by子句是在乙個sql語句執行的最後來實現的。sql是基於集合理論的,正因為集合中的行沒有預先確定的順序,排序就必須在符合查詢條件的資料行都被從集合中抽取出來之後再單獨進行。圖4-3給出了一種更恰當的方法來說明表中的內容是無序的。

看上去區分這些你在思考問題方式上的細小差別並不是那麼重要,但是這些細小的轉變是正確理解sql的基礎。讓我們來看乙個例子,通過面向過程的思維方式和基於集合的思維方式分別來寫乙個sql語句,以幫助你弄清楚二者之間的區別。

面向過程vs.基於集合的思維方式:乙個例子

在這個例子中,任務是要計算出乙個顧客在各個訂單之間的平均天數。**清單4-2給出了通過面向過程的思維方式的實現方法。為了讓例子的輸出較短,我將只計算乙個顧客的,但是由此可以很容易地轉變為計算所有顧客的。

**清單4-2 面向過程的思維方式

這看上去相當優雅,不是嗎?在這個例子中,我依次執行了一系列查詢來展示我是如何思考的,並按照逐步進行的過程方法來書寫查詢語句。如果你對分析函式lag的使用方法還不是很熟悉,不必擔心,分析函式將在第8章進行講解。簡單來說,我所做的事情就是按照orderdate的順序讀取102號顧客的每一行訂單資訊,然後使用lag函式,回過頭再看前一行的訂單資料以獲得該行的orderdate。當得到這兩個order_date(當前訂單行的日期以及前一行訂單的日期)以後,利用這兩個日期相減得出中間相差的天數就非常簡單了。最後,我使用求平均值聚合函式來得到最終的答案。

你可能會指出這個查詢是按照非常過程化的方式建立起來的。理解這種方式最好的辦法就是依次來看幾個不同的查詢以展示如何建立最終結果集的。在這個過程中我可以看到相關詳細資訊。當以基於集合的思維方式進行思考的時候,你會發現並不需要去關心每乙個單獨的元素。**清單4-3給出了乙個按照基於集合的思維方式來寫的查詢例子。

**清單4-

3基於集合的思維方式

這樣怎麼樣?我根本不需要任何花哨的技巧來解決這個問題。我用來計算訂單之間的平均天數所要做的事情就是計算出第一筆和最後一筆訂單之間的天數以及總的訂單數。我不需要一步一步地來考慮問題,正如我也不會寫乙個一行一行讀取資料然後計算出結果的程式。我所需要的就是把我考慮問題的思維方式轉變到將集合資料作為乙個整體來考慮。

我並不是完全無視過程化方法。可能有的時候你不得不採用這樣的方法來完成工作。然而,我想鼓勵你進行思維方式的轉變:首先尋找基於集合的方式,只有在需要的時候才採用更大程度的過程化方法。通過這樣做,你可能會發現自己可以得到更簡單、直接的,通常效能也更好的解決方案。

物件導向的思維方式

第一,首先確定誰來著,其次確定怎麼做 對比一下c語言,c語言要實現乙個功能,比如說要求乙個數的平方根,只要呼叫乙個函式就可以求出來,但在物件導向裡面不是這樣,首先應該考慮的是,求平方根的這件事應該是誰的任務,或者說是由誰來著,其次考慮怎麼去做,這才是物件導向。第二,首先考慮整體,其次考慮區域性 我就...

物件導向的思維方式

物件導向的思維方式 物件導向是圍繞物件和類來分析 設計軟體系統的。物件導向分析 物件導向分析的主要任務是根基使用者的需求,建立乙個準確的 完整的 一致的系統模型。在物件導向的分析過程裡,專案 組通過分析軟體的功能性需求,得到乙個理想化的系統模型,該模型更多的側重於描述我們需求解決的問題是什麼 我們稱...

物件導向的思維方式

物件導向是一種思維方式,也是一門程式設計技術 通俗的說,當你要解決乙個問題前,首先考慮的是由誰來做,而我們自己不考慮怎麼做的,怎麼做是這個誰的職責,最後把事情解決就行。而這個誰,就是物件 而要解決乙個複雜的問題,就可以找多個不同的物件,各司其職,共同合作,最終完成需求,這就是面向思維方式。下面分別從...