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

本文來自:http://www.ituring.com.cn/article/details/472

  為了以有趣的方式更好地幫助你形成面向集合的思維方式,我將給出自己最喜歡的游戲之一——集合。你可以在線玩這個游戲,網址是www.setgame.com/puzzle/set.htm,每天都會貼出一個新的集合謎題。集合游戲是一個每張卡片上有4個特征的謎題:顏色、符號、底紋以及符號的個數。顏色有紅、綠和紫色。符號有花體、方塊以及橢圓。底紋可以是實的、斑點的及外輪廓線。至于符號個數,每張卡上可能有一個、兩個或三個符號。要成為集合只有一條規則:一個集合只需要3張卡上的每一種單獨的特征要么都一樣要么全不相同。因此,一個有效的集合的例子就是3張卡上有相同的符號(例如方塊),3張卡上都有兩個符號,3張卡的顏色各不相同,并且3張卡都是實心圖案。所有使得3張卡上具有相同特征或者完全不同特征的組合都能構成集合。游戲的目標就是在12張卡中尋找集合。當找到一個集合后,這3張卡片就將被去掉,并加入3張新卡片。在在線版本中,12張卡片總會有6個集合,你的目標就是要找出所有這6個集合。

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

enter image description here

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

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

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

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

enter image description here

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

enter image description here

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

代碼清單4-1 過程化與基于集合的方法的對比

enter image description hereenter image description hereenter image description here

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

enter image description here

  處理流程圖表明結果集(A)是通過一系列以其他步驟為基礎的處理步驟來產生的最終答案。B通過遍歷C和D得出,然后A通過遍歷B和E得出。但是,嵌套集合圖中將A看做是不同集合的組合的結果。

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

enter image description here

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

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

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

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

enter image description here

enter image description here

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

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

代碼清單4-3 基于集合的思維方式

enter image description here

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

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


轉載于:https://www.cnblogs.com/qianqian0313/archive/2011/10/31/2394845.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/380136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/380136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/380136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

轉載: 統計圖控件NetCharting 和ZedGraph的比較

原文出處:http://hi.baidu.com/goga/blog/item/07b3024f61b8cd35aec3ab47.html最近考察了幾個統計圖表控件包,開源的有ZedGraph,Nplot等,但是相比之下還是ZedGraph強大,方便一些,其他的感覺還是半成品。收費…

【匯編語言】狀態標志符(CF/OF/SF/ZF)在運算(ADD/SUB/ADC/SBB)過程中的響應變化

目錄各類運算時狀態標志的響應變化標志符在各種ADD運算下的響應情況標志符在各種SUB運算下的響應情況借助標志符實現多位數之間運算ADC(add with carry)帶進位加法指令SBB(subtract with borrow)帶借位減法指令各類運算時狀態標志的響應變化 標志符具體含義CF(Carr…

Java集合unmodifiableSortedSet()方法(帶示例)

集合類unmodifiableSortedSet()方法 (Collections Class unmodifiableSortedSet() method) unmodifiableSortedSet() method is available in java.util package. unmodifiableSortedSet()方法在java.util包中可用。 unmodifiableSortedSet() method is used to get a non-modi…

遠控免殺專題(16)-Unicorn免殺

0x01 免殺能力一覽表 幾點說明: 1、上表中標識 √ 說明相應殺毒軟件未檢測出病毒,也就是代表了Bypass。 2、為了更好的對比效果,大部分測試payload均使用msf的windows/meterperter/reverse_tcp模塊生成。 3、由于本機測試時只是安裝了360全…

面向對象(匿名內部類在開發中的應用)

匿名內部類在開發中的應用 public class test1_NoNameInner {public static void main(String[] args) {PersonDemo yy new PersonDemo();//yy.method(new Student());yy.method(new Person() {public void show(){System.out.println("show");}});//匿名內部類當作…

【匯編語言】乘法(MUL/IMUL)

乘法(MUL/IMUL) 目錄乘法(MUL/IMUL)IMUL(signed multiply)有符號數乘法MUL(unsigned multiply)無符號數乘法麻!屬實是被這個有符號乘法給整麻了,教材就一行例子直接不解釋了,關于標志位溢出的一…

【轉】MFC學習總結

HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if ((pWnd->GetDlgCtrlID() IDC_EDIT1) && (nCtlColor CTLCOLOR_EDIT)) {   COLORREF clr RGB(255,0,0);   pDC->SetTextColor(clr);  //設置紅色的文本   clr RGB(0,0,0…

NHibernate初學體驗進階篇

在上篇《NHibernate初學體檢記》中&#xff0c;我參照NHibernate官方快速指南寫了兩個示例項目&#xff0c;在示例2的源碼中充斥了如下類似的代碼&#xff1a;<?XML:NAMESPACE PREFIX O />Configuration cfg new Configuration(); cfg.AddAssembly("…

eclipse快捷鍵

Java開發工具(Eclipse的視窗和視圖概述) A:視窗 每一個基本的窗體被稱為視窗 PackageExplorer 顯示項目結構&#xff0c;包&#xff0c;類&#xff0c;及資源Outline 顯示類的結構&#xff0c;方便查找&#xff0c;識別&#xff0c;修改Console 程序運行的結果在該窗口顯示Hie…

【匯編語言】除法(DIV/IDIV)

除法&#xff08;DIV/IDIV&#xff09; 目錄除法&#xff08;DIV/IDIV&#xff09;DIV(unsigned divide)無符號數除法IDIV(signed divide)有符號數除法DIV(unsigned divide)無符號數除法 格式&#xff1a;DIV SRC 操作&#xff1a; SRCSRCSRC為字節時&#xff0c;(AL)←(AX)/…

java 方法 示例_Java集合syncedSortedSet()方法與示例

java 方法 示例集合類SynchronizedSortedSet()方法 (Collections Class synchronizedSortedSet() method) synchronizedSortedSet() method is available in java.util package. java.util軟件包中提供了sharedSortedSet ()方法 。 synchronizedSortedSet() method is used to …

遠控免殺專題(17)-Python-Rootkit免殺

免殺能力一覽表 幾點說明&#xff1a; 1、上表中標識 √ 說明相應殺毒軟件未檢測出病毒&#xff0c;也就是代表了Bypass。 2、為了更好的對比效果&#xff0c;大部分測試payload均使用msf的windows/meterperter/reverse_tcp模塊生成。 3、由于本機測試時只是安裝了360全家桶…

項目管理軟件應用淺析(轉)

項目管理是在一定的約束條件下&#xff0c;以高效率地實現項目業主的目標為目的&#xff0c;以項目經理個人負責制為基礎和以項目為獨立實體進行經濟核算&#xff0c;并按照項目內在的邏輯規律進行有效的計劃、組織、協調、控制的系統管理活動。項目管理的核心技術是網絡計劃技…

斜視角的討論(轉)

http://school.ogdev.net/listshow.asp?page4&typeid0&categoryid5&id0&ListType2 目 錄 1.1 地圖和地表 1.2 斜視角游戲中的視角 1.3 Tile圖片的拼接 1.4 不同地表間的過渡 1.5 地圖數據結構的定義 --------------------------------------------------…

計算機網絡(湖科大教書匠)

計算機網絡&#xff08;湖科大教書匠&#xff09; 本文檔為教學視頻【計算機網絡微課堂&#xff08;有字幕無背景音樂版&#xff09;_嗶哩嗶哩_bilibili】的摘錄 目錄計算機網絡&#xff08;湖科大教書匠&#xff09;一、緒論1.2 因特網概述1.2.1 網絡、互連網&#xff08;互聯…

經緯度

題目描述 給定地球的兩個經緯度坐標&#xff0c;問這兩個點的直線距離。假設地球為球體&#xff0c;半徑為6371009米。 輸入描述: 第一行一個整數T表示數據組數。 接下來n行&#xff0c;每行四個數lat1, lng1, lat2, lng2分別表示兩個點的經緯度。 正數表示北緯和東經。 …

遠控免殺專題(18)-ASWCrypter免殺

免殺能力一覽表 幾點說明&#xff1a; 1、上表中標識 √ 說明相應殺毒軟件未檢測出病毒&#xff0c;也就是代表了Bypass。 2、為了更好的對比效果&#xff0c;大部分測試payload均使用msf的windows/meterperter/reverse_tcp模塊生成。 3、由于本機測試時只是安裝了360全家桶…

Hibernate 筆記4 實現對數據庫的增刪改查

1 準備 首先在mysql數據庫中建表User,并添加相關信息。 user表結構如下。 ---------------------------------------------------------| Field | Type | Null | Key | Default | Extra |------------------------------------------------…

Direct3D中的繪制(3)

立方體——只比三角形稍微復雜一點&#xff0c;這個程序渲染一個線框立方體。 這個簡單的繪制和渲染立方體的程序的運行結果如下圖所示&#xff1a; 源程序&#xff1a; /************************************************************************************** Renders a …

遠控免殺專題(19)-nps_payload免殺

免殺能力一覽表 幾點說明&#xff1a; 1、上表中標識 √ 說明相應殺毒軟件未檢測出病毒&#xff0c;也就是代表了Bypass。 2、為了更好的對比效果&#xff0c;大部分測試payload均使用msf的windows/meterperter/reverse_tcp模塊生成。 3、由于本機測試時只是安裝了360全家桶…