


版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、VisualFoxPro中的SQLSelect查詢基本的SQLSelect2From子句2Select子句2SQL和用戶自定義函數(shù)2Select子句中的關(guān)鍵字和其它子句3Select子句中的通配符3字段別名(AS)3用DISTINCT消去重復(fù)的記錄4用WHERE子句說明選擇記錄的條件4選擇條件4連接條件4SQL和宏4SQL和字母大小寫5SQL和索引5用OrderBy子句對結(jié)果排序5列函數(shù)6SQL的列函數(shù)6列函數(shù)中的DISTINCT6列函數(shù)的嵌套7用GROUPBY求分組小計(jì)9GROUPBY和DISTINCT之間的選擇9HAVING子句的使用10用TOP子句選擇一定數(shù)量或一定百分比的記錄13查詢結(jié)
2、果的輸出定向14復(fù)雜查詢15子查詢15帶子查詢的IN謂詞和量詞15ANY|SOME16ALL16EXISTS17自身連接17合并18示例一.快速排名次19示例二.選擇重復(fù)的記錄20外連接21什么是外連接?21用右外連接(RightOuterJoin)選擇記錄21用左夕卜連接(LeftOuterJoin)選擇記錄22用完全外連接(FullOuterJoin)選擇記錄23用內(nèi)連接加外連接選擇記錄24用內(nèi)連接(InnerJoin)選擇記錄25用嵌套的連接(NestedJoin)選擇記錄25VisualFoxPro5.0中的新的FROM/JOIN語法26為了更加清晰27用SQLSelect生成視圖28
3、注意事項(xiàng)29基本的SQLSelectFrom子句在FROM子句中指定要查詢的表,若指定的表未打開,F(xiàn)oxPro將自動打開指定的表,但在查詢完成后,FoxPro并不自動關(guān)閉它所打開的表,若要在查詢完成后關(guān)閉表,則必須以手動方式關(guān)閉它們。若在執(zhí)行SQLSELECT時(shí),F(xiàn)ROM子句中指定的表已經(jīng)打開,貝UFoxPro以USE-AGAIN的方式重新打開此表。Select子句SELECT子句中指定要查詢的結(jié)果字段,這些結(jié)果可以是以下基本元素:通配符*表中的字段名FoxPro函數(shù)SELECT中可用的列函數(shù)用戶自定義函數(shù)常數(shù)(常用于作為占位符)以上各元素在SELECT子句中以逗號分開,例如:SELECT銷售
4、地區(qū),銷售部門,業(yè)務(wù)員;FROM銷售表若SELECT子句中的字段名是唯一的,則不必在字段名前加別名修飾,SQL能自動找到這些字段。若字段名是非唯一的(即同一字段名出現(xiàn)在FROM子句中的兩個或兩個以上表中),F(xiàn)oxPro返回以下錯誤信息:字段|變量不唯一,必須加以限定要糾正這一錯誤,用字段所在表的別名修飾該字段。若在SELECT子句中加入了FoxPro函數(shù),則意味著該語句不具備可移植性。SQL和用戶白定義函數(shù)FoxPro支持在Select子句中使用用戶定義函數(shù)。但是由于在其它系統(tǒng)中不支持用戶定義函數(shù)。因此在開發(fā)可能移植的系統(tǒng)時(shí)不要使用用戶自定義函數(shù)。Select子句中的關(guān)鍵字和其它子句Selec
5、t子句中的通配符1、大(星號)只能使用在字段串列參數(shù)中。代表來源數(shù)據(jù)庫中所有的字段。如果select是在二個以上的數(shù)據(jù)庫中進(jìn)行查詢的,則要在號碼前加上數(shù)據(jù)庫別名。*是SQL中的三個通配符之一(其它兩個是?和_,將在以后討論),*只能出現(xiàn)在Select子句中,通配符前可以用別名修飾,在此情況下表示要查詢指定工作區(qū)中的全部字段.同時(shí)還可以給出其它字段名.如:Select銷售表.*,客戶表.客戶代碼,客戶表.客戶名稱;FROM銷售表,客戶表;WHERE銷售表.客戶代碼=客戶表.客戶代碼2、(百分號)只能使用在Where參數(shù)中,代表一連串任意字符類似于DOS下的IT*.PRG中的”通常與運(yùn)算符LIKE
6、搭配使用:SELECT客戶名FROM客戶表WHERE客戶名LIKE成都公司”以上查詢選擇所有公司名以”成都”開始,以”公司”結(jié)尾的客戶,如:成都東方公司、成都西部發(fā)展公司等。3、_(下劃線)也只能使用在where參數(shù)中,代表一個任意字符。與DOS下的DIRIT?.PRG中的”?”一樣。例如_a%表示第二個字符為a的字串。通常與LIKE搭配使用:SELECT客戶名FROM客戶表WHERE客戶名LIKE成都公司”以上查詢選擇類似于”成都分公司”,成者E總公司”這樣的公司名字。另一種情況是文字?jǐn)?shù)據(jù)中正好包含有星號、百分號、下劃線(例如:軟件部業(yè)務(wù)組),此時(shí)可使用關(guān)鍵字ESCAPE告訴SQL哪一個字符
7、是常數(shù)字符而非通配符。例如:selectcompanyfromcustomerwherecompanylike"%_%"escape""此時(shí)escape所指定字符(即)后的那一個字段(此處為下劃線_)將被視為常數(shù)字符而非通配符。字段別名(AS)FoxPro提供了給Select子句中的字段起別名的方法(這種方法不同于ANSI/ISO標(biāo)準(zhǔn)):即可用AS子句給出Select子句中字段的別名,在多當(dāng)需要直接瀏覽查詢結(jié)果或查詢結(jié)果中含有計(jì)算列時(shí),該方法很有用處.例如:SELECT物資部”AS部門,SUM(工資)AS工資匯總;FROM工資表WHERE部門編號=“00
8、13”用DISTINCT消去重復(fù)的記錄SELECT中的DISTINCT關(guān)鍵字,可以消去查詢結(jié)果中的重復(fù)行。例如要字段出所有購買了商的客戶,可以用以下Select語句:SELECTDISTINCT客戶名稱;FROM銷售細(xì)節(jié)表注意,這里消去的重復(fù)記錄是指SELECT子句中的所有字段值均相等的記錄.當(dāng)SQL遇到DISTINCT關(guān)鍵字時(shí),即建立一個中間表。然后以SELECT子句中的所有字段建立一個唯一索引,然后將索引用于中間表,并把索引中的記錄放入查詢結(jié)果中。這樣就消去了重復(fù)記錄,但是當(dāng)SELECT子句中的字段很多時(shí),這一過程會很慢。用WHERE子句說明選擇記錄的條件通常查詢并不希望取出所有記錄,而只
9、是希望查出滿足一定條件的記錄,要做到這一點(diǎn)可以使用WHERE子句。WHERE子句把滿足條件的記錄作為查詢結(jié)果。選擇條件在WHERE子句中可以包含多個選擇條件,各條件間用AND或OR連接而構(gòu)成較長的邏輯表達(dá)式。連接條件當(dāng)一個查詢涉及到多個表時(shí),需要一個特殊類型的WHERE條件,稱為連接條件,連接條件建立了FROM子句中的兩表間的一對一或一對多的聯(lián)系。SQL和宏SELECT子句中可以方便快捷地處理宏,在SELECT語句中,宏替換只能替換一次,在以下查詢之前,需要由用戶給出表名和相應(yīng)的表達(dá)式Select*;FROM(UserTable);Where公司代碼=&Company_code宏還可以
10、用在LIKE的模式匹配串:SelectCompany,CompanyId,SaleName,SaleId;FromCompany,SalesMan;WhereCompany.SaleId=SalesMan.SaleId;ANDDescriptionLIKE"%TCL%"以上查詢中,用戶輸入一字符串以便在備注字段(Description)中作匹配查找.查詢求出的是包含該字符串的所有公司的住處SQL和字母大小寫SQL中是區(qū)分字母大小寫的,為使查詢結(jié)果有效,要注意區(qū)分查詢條件中的大小寫.中表中的內(nèi)容是大寫的查詢時(shí)必須將它們轉(zhuǎn)換為大寫.若表中內(nèi)容是大小寫混雜的,則以下Select語
11、句將難以返回全部結(jié)果:SelectCompanyld;FromCompany;WhereCompanyld="ACME”以上查詢只返回名為ACME的記錄,對于Companyld為Acme的記錄則查不到,因此安全的方法是用UPPER()函數(shù)將所有字符串都轉(zhuǎn)換為大寫.以下是正確的查詢:SelectCompanyld;FromCompany;WhereUPPER(Companyld)="ACME"SQL和索引WHERE條件可用Rushmore和索引加速查找.SQL可用任何類型的索引:結(jié)構(gòu)化的.CDX,外部的.CDX及外部的.IDX.若要使SQL使用外部索引,必須在執(zhí)行S
12、elect之前將其打開,如以下語句所示:UseSalesINDEXidxcdxfileSQL可以以同樣的方式作為標(biāo)準(zhǔn)過程代碼使用Rushmore.這時(shí)選擇條件必須是可優(yōu)化的,即選擇表達(dá)式必須與建立索引的表達(dá)式精確匹配.用OrderBy子句對結(jié)果排序由于SQL優(yōu)化器是按它認(rèn)為的最佳方案去存取數(shù)據(jù),因些查詢結(jié)果中的記錄順序是動態(tài)不定的.許多應(yīng)用程序需要查詢結(jié)果是按一個或多個字段排好序的.為此可用ORDERBY子句.ORDERBY子句可以包含Select子句中一樣多的字段.例如:SelectCompany,State,CompanyId;FromClient;WhereStateIN("N
13、Y","NJ","PA","CA");OrderByState,Company在以上查詢中,按所在州及公司名稱順序給出結(jié)果.缺省情況下,記錄是升序排字段,也可用DESCENDING來說明按降序排序.當(dāng)然也可以升降序并用,例如:SelectCompany,State,CompanyId,SaleNo;FromCompany,Sales;WhereCompany.Saleld=SalesMan.Saleld;ANDStateIN("NY”,"NJ”,"PA”,"CA”);ORDERBYSt
14、ate,Company,SaleNoDESCENDING以上查詢結(jié)果首先按州及公司名稱升序排字段,然后按SaleNo降序排序.由于排序是對查詢結(jié)果的排序,因此OrderBy子句中的字段必須是Select子句中出現(xiàn)的字段.另外,OrderBy子句允許用位標(biāo)號給出排序字段,這些位標(biāo)號是指Select子句中出現(xiàn)的序號.例如上一個查詢可以寫為:SelectCompany,State,CompanyId,SaleNo;FromCompany,Sales;WhereCompany.Saleld=SalesMan.Saleld;ANDStateIN("NY","NJ"
15、,"PA","CA");ORDERBY2,1,3DESCENDING當(dāng)Select子句包含了用戶定義函數(shù)或FoxPro函數(shù)(如UPPER()和LEFT()時(shí),用位標(biāo)號來給出排序字段顯得十分方便.列函數(shù)在Select子句中,可以用SQL提供的五個列函數(shù),如下表所示:SQL的列函數(shù)函數(shù)描述AVG(字段名)求出指定字段上的平均值,只適用于數(shù)值型的字段SUM(字段名)求出指定字段上的和,只適用于數(shù)值型的字段MIN(字段名)求出指定字段上的最小值,字段可以是數(shù)值型,字符型或日期型MAX(字段名)求出指定字段上的最大值,字段可以是數(shù)值型,字符型或日期型COUNT(字
16、段名)求出指定字段上的值的出現(xiàn)個數(shù),可以用COUNT(*)求出記錄數(shù)所有列函數(shù)的結(jié)果都是單值關(guān)于列函數(shù),別有以下需要注意的地方列函數(shù)中的DISTINCT可以在任一個列函數(shù)中(除了MIN()和MAX()使用DISTINCT,這樣在列函數(shù)的求值中將不計(jì)重復(fù)值.例如:SELECTAVG(DISTINCTSalesPrice);FROMSales在以上查詢中,求出商品的銷售單價(jià),對于重復(fù)的SalesPrice,只計(jì)算一次.注意在Select子句中只能使用一次DISTINCT.以下查詢是不正確的:SELECTDISTINCTAVG(DISTINCTSalesPrice),SalesMan;FROMSal
17、es還有一點(diǎn)要注意的是,在COUNT()函數(shù)中,*不能與DISTINCT連用(如COUNT(DISTINCT*),若在COUNT()中使用DISTINCT,需給出字段名.列函數(shù)的嵌套以下查詢是列函數(shù)嵌套的情況:SelectSUM(AVG(SalesPrice),SalesMan;FromSales;GroupByProduct_ID該查詢是想求出每一產(chǎn)品的平均單價(jià)的和,但在運(yùn)行時(shí)FoxPro會給出如下錯誤:文件"AVG.prg"不存在這說明列函數(shù)是不能嵌套使用的.例一:人員資料表ryb,內(nèi)容如下:科室姓名職稱政治面貌辦公室awfw助工黨員通訊科wafawe局工黨員機(jī)械科af
18、awe技術(shù)貝團(tuán)員財(cái)務(wù)科2wraw無無人事科afwe工程師無現(xiàn)要統(tǒng)計(jì)每個科室各有幾名技術(shù)員、助工、工程師、高工、黨員、團(tuán)員,以下列表的形式打印出來科室技術(shù)貝助工工程師(Wj-L黨員團(tuán)員財(cái)務(wù)科223343命令如下:Select科室,;sum(iif(職稱="技術(shù)員",1,0),;sum(iif(職稱="助工",1,0),;sum(iif(職稱=”工程師",1,0),;sum(iif(職稱="高工",1,0),;sum(iif(政治面貌="黨員",1,0),;sum(iif(政治面貌="團(tuán)員"
19、;,1,0);fromrybgroupby科室例二:表recdbf性質(zhì)分一般、重大、特大;日期12個月內(nèi)每個月每種性質(zhì)的記錄各有多少,若該月沒有記錄就為零。結(jié)果:月份一般重大特大10132212312305要統(tǒng)計(jì)出某年的這跟上面那個例子有點(diǎn)不同,上例只是按表中科室來分類,而這里就不同,因?yàn)椴皇敲總€月都有案件的,但在報(bào)表里沒有案件的月也要占一行。所以這里要建立一個輔助表:tempyf(yfN(2),內(nèi)有十二個記錄,值為1至12,代表112月。我先是老規(guī)則:Selectmonth(日期),;iif(性質(zhì)=”一般”,1,0)as一般,;iif(性質(zhì)="重大",1,0)as重大,;
20、iif(性質(zhì)="特大",1,0)as特大;fromrecdbf;whereyear(日期)=?年份;intocurstemp1再用tempyf左聯(lián)接臨時(shí)表temp1,根據(jù)tempyf.yf分組統(tǒng)計(jì)。但一看,結(jié)果好象不對,沒有記錄的月份不在結(jié)果當(dāng)中,而且這兩條select好象可以合而為一。SELECTtempyf.*,;SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdbf.以上查詢可以更簡潔地使用以下命令:日期)ORAT("一般",recdbf.性質(zhì))=0,0,1)AS一般,;日
21、期)ORAT("重大",recdbf.性質(zhì))=0,0,1)AS重大,;日期)ORAT("特大",recdbf.性質(zhì))=0,0,1)AS特大;FROMtempyfLEFTOUTERJOINrecdbf;ONtempyf.yf=MONTH(recdbf.日期)ANDYEAR(日期)=?yy;&&注意這里,on后面是可以加上其它條件的GROUPBYtempyf.yf在上例中,yy是指具體那一年,如果不指定的話,那就是把表中所有的記錄算在一起。而且如果要指定具體那一年的話,那這個YEAR(日期)=?yy的條件是不能放在where或者h(yuǎn)aving里
22、的。以上查詢的另一個有趣的地方是:sum命令是可以直接累加肝的結(jié)果,而且過濾條件從where移到on后會發(fā)生這么大的差別!在where時(shí),是先聯(lián)接統(tǒng)計(jì)后再過濾,結(jié)果把那些沒有記錄的月份也過濾掉了;而在on是先過濾再聯(lián)接、統(tǒng)計(jì),過濾結(jié)果中雖然沒有記錄的月份也不在其中,但因是左聯(lián)接,也一樣會以null代替,但給肝中的isnull給變成了0.注:其中那個ONtempyf.yf=MONTH(recdbf.日期)ANDYEAR(日期)=?yy在視圖生成器中是不能直接做的,而只能用Createsqlviewas以命令的方式生成。用GROUPBY求分組小計(jì)GROUPBY的意思是按給定字段進(jìn)行分組,所謂分組就
23、是將一組類似的記錄壓縮成一個結(jié)果記錄,這樣就可以完成基于一組記錄的計(jì)算。例如,若想找到某一特定地區(qū)所有訂貨的總和,不用單獨(dú)查看所有的記錄,可以把來自相同地區(qū)的所有記錄合成為一個記錄,并獲得來自該地區(qū)的所有訂貨的總和。分組在與某些合計(jì)函數(shù)聯(lián)合使用時(shí)效果最好,諸如SUM、COUNT、AVG等等。例如,若想看到訂單表中具有特定ID號的客戶訂貨的金額總值,只需將具有相同CustomerID號的訂貨記錄合成為一個記錄,同時(shí)尋找訂貨總量即可。GROUPBY和DISTINCT之間的選擇如果在字段串列中沒使用字段函數(shù),則groupby參數(shù)與關(guān)鍵字distinct的效果相同。不過使用groupby參數(shù)的效果顯然
24、要比使用關(guān)鍵字distinct來得快,而且在字段串列中的字段數(shù)越多,速度的差距會越大。如果在字段串列中使用字段函數(shù)且使用groupby參數(shù),則仍會顯示出多個數(shù)據(jù)記錄。但是如果于字段串列中使用字段且使用關(guān)鍵字distinct,則只有一個數(shù)據(jù)記錄會顯示出來。顯然有字段時(shí)應(yīng)使用groupby參數(shù)。例子:1、selectname,max(salary)fromtestgroupbyname2、selectdistctname,max(salary)fromtest結(jié)果:grouybydistinctnamesalarynamesalarynamesalaryalex20alex90mary95alex
25、10mary44alex50tom95alex90alex30tom45tom55tom15tom95mary33mary44HAVING子句的使用我們已經(jīng)可以求分組小計(jì),但另一問題是:如何控制或篩選分組?這里不能用WHERE子句,因?yàn)樗荒軐碇械挠涗涀骱Y選。而我們要篩選的是中間表的分組記錄。HAVING子句可用于控制從中間表到最終結(jié)果的過濾。雖然在HAVING子句中可以用任何合法的字段或表達(dá)式,但一般是用列函數(shù)。原因是HAVING子句要跟在GROUPBY子句后使用,這意味著SELECT子句中有列函數(shù),例如:SELECTSALE_NO,SUM(SALE_AMOUNT)ASAMOUNT;FR
26、OMSALEITEM,SALES;WHERESALES.SALE_NO=SALEITEM.SALE_NO;GROUPBYSALE_NO;HAVINGSUM(SALE_AMOUNT)>1000以上查詢求出銷售金額超過1000元的銷售單及金額。HAVING子句中的列函數(shù)不必與SELECT子句中的列函數(shù)相同,例如SELECTSALE_NO,SUM(SALE_AMOUNT)ASAMOUNT;FROMSALEITEM,SALES;WHERESALES.SALE_NO=SALEITEM.SALE_NO;GROUPBYSALE_NO;HAVINGAVG(SALE_AMOUNT)>100此查詢求出
27、平均商品金額在100元以上的銷售記錄,結(jié)果中要求給出銷售單的總金額。WHERE和HAVING都為查詢提供過濾條件,經(jīng)常有人問哪一個要好些。答案是,為了獲取更好的性能,應(yīng)該用WHERE子句來過濾一般表的記錄,而用HAVING過濾GROUPBY后的分組結(jié)果。另外,使用HAVING子句時(shí)容易犯的一個錯誤是:SELECT*FROMSALESHAVINGSALESMAN_ID='001”雖然以上查詢也可運(yùn)行,但不能利用RUSHMORE,因此要比以下查詢慢數(shù)百到數(shù)千倍:SELECT*FROMSALESWHERESALESMAN_ID='00'1”示例:對于HAVING子句,sele
28、ct的條件過濾的先后順序是這樣的:先對join中的on表達(dá)式進(jìn)行過濾,再到where,中間結(jié)果出來后再用having進(jìn)行過濾,最后才把結(jié)果顯示出來。所以說having是對select結(jié)果的最后一次過濾。它與where的分別就是where能夠事先把不要的數(shù)據(jù)過濾掉,這樣select里頭就不用處理那么多的數(shù)據(jù)。但有些數(shù)據(jù)事先不知道要不要過濾,要根據(jù)結(jié)果才能確定,這時(shí)才用having這個事后諸葛亮。這里用例子來比較一下on、where、having的不同之處表recdbf內(nèi)容如下:還有一個tempyf的輔助表,記錄日期性質(zhì)yf2000年7月3日特大12000年7月9日特大22000年9月3日特大31
29、999年3月2日一般41999年3月4日一般52000年1月3日一般62000年2月1日一般72000年2月3日一般82000年3月4日一般92000年8月7日一般102000年11月2日一般111999年2月3日重大122000年2月3日重大2000年5月2日重大2000年8月9日重大on的命令如下SELECTtempyf.*,;SUM(IIF(ISNULL(recdbf.日期).OR.AT("一般",recdbf.性質(zhì))=0,0,1)AS一般,;SUM(IIF(ISNULL(recdbf.日期).OR.AT("重大",recdbf.性質(zhì))=0,0,1
30、)AS重大,;SUM(IIF(ISNULL(recdbf.日期).OR.AT("特大",recdbf.性質(zhì))=0,0,1)AS特大;12個月FROMtempyfLEFTOUTERJOINrecdbf;ONtempyf.yf=MONTH(recdbf.日期).AND.YEAR(日期)=?yy;GROUPBYtempyf.yf其中yy=2000,表示統(tǒng)計(jì)2000年的數(shù)據(jù)SELECTtempyf.*,;SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdbf.用where的命令如下:日期).OR.AT(&q
31、uot;一般",recdbf.性質(zhì))=0,0,1)AS一般,;日期).OR.AT("重大",recdbf.性質(zhì))=0,0,1)AS重大,;日期).OR.AT("特大",recdbf.性質(zhì))=0,0,1)AS特大;FROMtempyfLEFTOUTERJOINrecdbf;ONtempyf.yf=MONTH(recdbf.日期);GROUPBYtempyf.yf;用having的命令如下:SELECTtempyf.*,;SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdbf.SUM(IIF(ISNULL(recdb
32、f.whereYEAR(日期)=?yy&&注意,條件從on移到這里來了日期).OR.AT("一般",recdbf.性質(zhì))=0,0,1)AS一般,;日期).OR.AT("重大",recdbf.性質(zhì))=0,0,1)AS重大,;日期).OR.AT("特大",recdbf.性質(zhì))=0,0,1)AS特大;FROMtempyfLEFTOUTERJOINrecdbf;ONtempyf.yf=MONTH(recdbf.日期);GROUPBYtempyf.yf;on的結(jié)果如下,這是正確的YF一般重大特大11002210310040005
33、0106000700281109001100001110012000用where的結(jié)果如下:YF一般重大特大110022103100501070028110用having的結(jié)果如下:YF一般重大特大11002220501070028110900111100以上查詢有什么不同呢?havingYEAR(日期)=?yy&&注意,條件從on移到這里來了on是把先把recdbf中不是2000年的記錄過濾掉,剩下的就是2000年的了,再用tempyf去和它們進(jìn)行外聯(lián)接,其結(jié)果可用selecttempyf.*,recdbf.日期;fromtempyfleftjoinrecdbf;ONtemp
34、yf.yf=MONTH(recdbf.日期).AND.YEAR(日期)=?yy;GROUPBYtempyf.yf來查看,這個中間結(jié)果出來后,再用isnull把空值的記錄變成0或1,然后由sum去統(tǒng)計(jì),結(jié)果就出來了而where呢,1、它是先把tempyf外聯(lián)接recdbf,相當(dāng)于selecttempyf.*,recdbf.*;fromtempyfleftjoinrecdbfontempyf.yf=mont(recdbf.日期)2、然后把不是2000的記錄過濾掉,這里要注意的是,如果某個月沒有記錄的話,那在第一個步驟后日期那里是null值,這當(dāng)然不是2000的記錄,所以就給這個條件給過濾出去了,所
35、以下一步的sum之后就只剩下那有記錄的那個月了,象4、6月等幾個月。就沒有3、然后進(jìn)行sum()再看having1、第一步和where一樣,2、第二步不同,它是先sum(),這里的sum可不管你是1999年還是2000的,先累加起來再說,這時(shí),1999和2000年的2月份都有“重大”這個記錄,sum的結(jié)果是2,這里用第三個步驟去分辨這個2之中那個是1999年的,那個是2000的,這當(dāng)然分不清啦,所以也錯了。3、根據(jù)步驟2來把2000的過濾出來。所以on、where、having這三個都可以加條件的子句中,on是最先執(zhí)行,where次之,having最后。但有時(shí)候如果這先后順序不影響中間結(jié)果的話
36、,那最終結(jié)果是相同的。但因?yàn)閛n是先把不符合條件的記錄過濾后才進(jìn)行統(tǒng)計(jì),它就可以減少中間運(yùn)算要處理的數(shù)據(jù),按理說應(yīng)該速度是最快的。根據(jù)上面的分析,可以知道where也應(yīng)該比having快點(diǎn)的,因?yàn)樗^濾數(shù)據(jù)后才進(jìn)行sum,所以having是最慢的。但也不是說having沒用,因?yàn)橛袝r(shí)在步驟3還沒出來都不知道那個記錄才符合要求時(shí),就要用having了。用TOP子句選擇一定數(shù)量或一定百分比的記錄TOP子句用來限定結(jié)果集中返回的記錄數(shù):結(jié)果集中的頭50條記錄TOP50頭25%TOP25PERCENT在查詢的結(jié)果集合中,如果只需要其中一定數(shù)量或百分比的記錄,可以在“查詢設(shè)計(jì)器”或“視圖設(shè)計(jì)器”中,使用
37、“雜項(xiàng)”選項(xiàng)卡上的“列在前面的記錄”屬性設(shè)置數(shù)量或百分比,也可以在SELECT-SQL命令中添加TOP子句。在TOP子句中,所允許的數(shù)值范圍為1至V32767;如果使用的是百分?jǐn)?shù),則范圍為0.001到99.99。例如,如果要選擇具有最高總訂貨量的前10位顧客,可以用GROUPBY指定CUST_ID字段,來顯示每個顧客的合計(jì)記錄,然后在ORDERBY子句中按照ORDER_AMT排序。若要得到最高的前十個記錄,需要在ORDER_AMT上面指定降序排列,從而使具有最高訂貨量的顧客在結(jié)果中最先顯示。如果使用升序排列,結(jié)果記錄則按照訂貨量由少到多的次序排列,那么在結(jié)果集合中選擇的前幾個記錄實(shí)際上是訂貨量
38、最少的。SELECTTOP10*FROMtestdata!customerINNERJOINtestdata!orders;ONCustomer.cust_id=Orders.cust_id;GROUPBYCustomer.cust_id;ORDERBYOrders.order_amtDESC查詢結(jié)果的輸出定向使用SELECT-SQL語句的各個子句,可以指定多種不同的輸出目標(biāo)來保存查詢結(jié)果。若要將查詢結(jié)果輸出到使用子句獨(dú)立的表INTOTABLEmytable數(shù)組INTOARRAYaMyArray臨時(shí)表INTOCURSORmycursor活動窗口TOSCREEN瀏覽窗口如果沒有指定其他目標(biāo),則用
39、它作默認(rèn)值。保存了查詢結(jié)果之后,您就可以使用命令將存儲的結(jié)果加以適當(dāng)組織,以便顯示或打印。將查詢結(jié)果存儲到表、數(shù)組或臨時(shí)表中查詢結(jié)果可以存儲到表、數(shù)組或臨時(shí)表中,以備它用,例如處理表單以及打印報(bào)表和標(biāo)簽。如果只想暫時(shí)保存結(jié)果,則可將它們發(fā)送到數(shù)組或臨時(shí)表中。若要永久保存結(jié)果,則應(yīng)該將它發(fā)送到一個表中。若要指定一個表作為輸出目標(biāo),用SELECT-SQL語句的INTO子句指定一個目標(biāo)。下面的示例演示了如何用一個INTO子句指定一個表:SELECT*;FROMtastrade!customer;WHEREcustomer.country="Canada"INTOTABLEmyta
40、ble若要指定一個數(shù)組作為目標(biāo),用SELECT-SQL語句的INTO子句指定一個目標(biāo)。下面的示例演示了如何用INTO子句指定一個數(shù)組。SELECT*;FROMtastrade!customer;WHEREcustomer.country="Canada"INTOARRAYaMyArray若要指定一個臨時(shí)表作為目標(biāo),用SELECT-SQL語句的INTO子句指定一個目標(biāo)。以下示例演示了如何用INTO子句指定一個臨時(shí)表。SELECT*;FROMtastrade!customer;WHEREcustomer.country="Canada"INTOCURSORm
41、ycursor復(fù)雜查詢復(fù)雜查詢是指需要多個Select語句來決定最后結(jié)果的查詢。傳統(tǒng)的講,復(fù)雜查詢包括子查詢,自身連接和合并。Select命令參數(shù)很多,功能也很強(qiáng)大,適當(dāng)?shù)氖褂靡恍┘记?,可以使程序更潔練,運(yùn)行速度更快。但如果不是很強(qiáng)求速度的話,我認(rèn)為太過復(fù)雜的命令對以后的維護(hù)工作帶來困難。呵呵,有時(shí)我要理解自己寫的命令都有點(diǎn)困難,實(shí)在是太復(fù)雜了。以下內(nèi)容是工在工作過程中摸索出來的一些小技巧,希望對別人有幫助。子查詢子查詢有時(shí)又叫內(nèi)部查詢(INNERQUERY),是一個嵌入到另一個SELECT中的SELECT語句。一個包括子查詢的語句通常情況下以以下幾種形式出現(xiàn):WHERE表達(dá)式NOTIN(子查
42、詢)WHERE比較操作符ANY|ALL(子查詢)WHERENOTEXISTS(子查詢)當(dāng)需要從一個查詢的結(jié)果來產(chǎn)生最終結(jié)果時(shí),一般要使用子查詢。使用子查詢時(shí)有如下限制:子查詢的SELECT子句中只允許有一個字段名,除非是在子查詢中使用*通配符。只能在主查詢中使用UNION和ORDERBY,而不能在子查詢中使用它們。子查詢必須用括號括起來。子查詢只能使用比較、包含、存在和量詞等條件。子查詢中的WHERE子句可引用主查詢中的字段,這稱為外部引用IN和NOTININ關(guān)鍵字用于決定一個特定值是否是內(nèi)部查詢所產(chǎn)生的結(jié)果列表值中的一個值。相反,NOTIN決定了某個特定值是否不存在于一個內(nèi)部查詢的結(jié)果集中。
43、對包含條件(IN關(guān)鍵字),子查詢的結(jié)果可以是一組數(shù)值。例如,在temp2中列出所有包含在tempi中的記錄。例一tempi記錄數(shù):90112temp2記錄數(shù)22528兩表均按name建立索引,temp2全部都是包含在tempi里的。用子查詢:Selecttemp2.*;fromtemp2;wherenamein(selenamefromtempi)1.542秒(有索引)4.596(無索引)用聯(lián)接:selecttemp2.*;fromtemp2;jointempi;=2.384秒(有索引)5.658(無索引)相關(guān)的時(shí)間都是有一秒左右。這應(yīng)該是因?yàn)樽硬樵?/p>
44、首先執(zhí)行,它把tempi中的一部分(name)讀入內(nèi)存,然后tempi再在其中進(jìn)行比較;而聯(lián)接則一開始就是讀文件,所以就慢了一點(diǎn)。例二列出沒有采購的公司:selectcompanyfromcustomer;wherecnonotin;(selectcnofrominvoices)在上例中,先用IN關(guān)鍵字進(jìn)行過濾,當(dāng)過濾的條件表達(dá)式cno未出現(xiàn)在invoices.Cno中時(shí)便被選擇出來。請注意where子句中的NOT關(guān)鍵字的用法,如果不用NOT關(guān)鍵字,則上面查詢的作用就是列出有采購的公司。IN查詢中的子查詢,匹配主查詢的一個值。可得出一組值來檢查包含關(guān)系。因此,當(dāng)希望由SQL產(chǎn)生一組有效值,而不
45、是由用戶輸入時(shí),可用IN子查詢的方式。量詞只適用于來子查詢的IN謂詞。IN謂詞只是簡單地判斷外部查詢的值是否與值表中的某一個值相等。量詞可擴(kuò)展這一包含關(guān)系,它可用于任何有效的比較符(如<,>,<>等等)。量詞可以是ANY、SOME或ALL。ANY|SOME列出ytdsales字段至少必須大于offices其中個select*fromsalesman;whereytdsales>ANY;(selectytdsalesformoffices)對于外部查詢的每一值,若小于子查詢結(jié)果的任一值A(chǔ)LL當(dāng)子查詢中的所有值都能符合夕卜部條件的比較符時(shí)歹U出ytdsales字段必須
46、大于salesman.ytdsalesytdsales字段之值。,則條件為真。在條件滿足后,即終止比較。,ALL返回真。若有一個不滿足,則停止處理并返回假值。字段的值。select*fromoffices;whereytdsales>ALL;(selectytdsalesfromsalesman)含有量詞的查詢經(jīng)常引起混淆,因?yàn)槌霈F(xiàn)的比較符常與要求中的相反。最后,量詞產(chǎn)生一個邏輯值而不是一個比較值。EXISTS和NOTEXISTS子查詢用EXISTS和NOTEXISTS測試來發(fā)現(xiàn)兩個集合間是否有交叉功區(qū)別。EXISTS(如果元素同時(shí)屬于兩個集合時(shí)為真)NOTEXISTS(如果只有第一個集
47、合包含了元素時(shí)為真)EXIST關(guān)鍵字的含意是:判定外查詢記錄的某些值是否在內(nèi)查詢表中存在。例如:列出沒有采購的公司:selectcompanyfromcustomer;wherecnonotexists;(select*;&&用exists這里一定要用星號"大”o=o)對于EXIST關(guān)鍵字有兩點(diǎn)要注意。首先,含EXIST關(guān)鍵字的查詢總是相關(guān)查詢:即,內(nèi)查詢必然引用外查詢的字段(如上例中的cno)。這使但存在謂詞的子查詢相當(dāng)慢,因因?qū)τ谕獠樵兊拿恳挥涗?,子查詢都要?zhí)行一遍。外查詢中要處理的記錄數(shù)越多,則查詢執(zhí)行時(shí)間越長。其次,EXIST關(guān)鍵字的子查詢是唯一允許用通配符的
48、*的情況。由于結(jié)果只有真或假,對說明什么字段無關(guān)緊要,因此可用通配符。實(shí)際中,存在謂詞的子查詢總是用*。存在謂詞只是標(biāo)準(zhǔn)的帶子查詢IN謂詞的特殊形式。一般來說,IN謂詞要快于存在謂詞。目前在實(shí)際的SQLSELECT中,其所有子查詢都處在同一級,都是作為主查詢的子查詢。這就是說,僅可在主查詢的選擇條件中使用子查詢。白身連接當(dāng)一個表中的信息要與同一表中其它信息相比較時(shí),需要用到自身連接。需要使用自身連接的有兩種典型情況一種是表中有多對多關(guān)系,一種是表中有跨越時(shí)間段的信息。示例:按業(yè)務(wù)員的銷售額的高低順序,顯示每一個業(yè)務(wù)員的銷售額,并伴隨顯示那些比他銷售還多的業(yè)務(wù)員的平均銷售額。Selecta.sa
49、lesman,,a.ytdsales,AVG(b.ytdsales)asbetter;fromsalesmanA,salesmanB;&&這里把salesman打開兩次,分別起個別名A和BwhereA.ytdsales<B.ytdsales;groupbyA.salesman;orderbyA.ytdsalesDESC相同于使用聯(lián)接:Selecta.salesman,,a.ytdsales,AVG(B.ytdsales)asbetter;fromsalesmaninnerjoinsalesmansalesman_a;onsalesman.ytdsa
50、les<salesman.ytdsales;;orderbysalesman.dddesc注:自連接時(shí)必須注意以下事項(xiàng):1、同一來源數(shù)據(jù)庫務(wù)必給予不同的別名;2、位于select命令語句的字段串列中各個字段前都必須中上別名;3、由于一旦自連接后即形成“多對多”的關(guān)聯(lián)性連接,因此請小心設(shè)定where參數(shù)的連接條件。在一個有1千個記錄的表中,執(zhí)行第一條命令要188.261秒,第二條命令要154.712秒。而500個記錄時(shí),第一條命令6.870秒,第二條7.190秒。雖然其中的數(shù)值有點(diǎn)不是很準(zhǔn)確,但這不重要,只要知道不要隨便使用這種方法就行了。合并與其它
51、復(fù)雜查詢不同,UNION實(shí)際上是SELECT語句上的子句。UNION可以把來自兩個或多個獨(dú)立的SELECT語句的信息合并為一個結(jié)果。在多數(shù)情況下是用UNION把不相關(guān)表的信息合并起來。UNION有一個可選的子句ALL。與SELECT語句不同,UNION在默認(rèn)情況下使用DISTINCT消去結(jié)果中的重復(fù)記錄。若要提高UNION的速度,可用ALL選項(xiàng),這樣免去UNION消去重復(fù)記錄的操作。為什么UNION在默認(rèn)情況下要用DISTINCT?這是由這一操作的特性決定的。當(dāng)把兩個不相關(guān)的表合并為一個結(jié)果時(shí),同一記錄可能存在于兩個表中。與SELECT子句中的DISTINCT一樣,當(dāng)使用DISTINCT時(shí)會使
52、UNION的速度下降。因此,如果基于對應(yīng)用程序和表的了解,知道不會有重復(fù)記錄或重復(fù)記錄很少,這時(shí)可用ALL來減少執(zhí)行時(shí)間。象子查詢一樣,UNION要成功地執(zhí)行,需遵循以下規(guī)則:UNION僅用于外查詢,不能用UNION合并子查詢。使用UNION的SELECT子句必須有相同的字段數(shù),相同的數(shù)據(jù)類型和相同的長度和精度,因?yàn)镾QL需把SELECT語句的結(jié)果合并到一張表中。為此SQL使用第一個查詢語句的SELECT子句作為結(jié)果表的結(jié)構(gòu)。若UNION中的其它查詢中的語句中的字段需在結(jié)果中,則必須出現(xiàn)在第一個查詢的SELECT子句中。若第一個SELECT子句中的某字段不在其它查詢語句中的表中,則該字段仍必須
53、出現(xiàn)在這些查詢語句的SELECT子句中。具體的例子如下:在做生產(chǎn)管理時(shí),原材料的每筆進(jìn)貨、領(lǐng)用、報(bào)廢、退貨情況都要詳細(xì)記錄,老板隨時(shí)都可能了解一個月內(nèi)每種原材料的各種情況。而編程時(shí)對數(shù)據(jù)的規(guī)范化后,必然要用好幾個表來記錄這四種操作?,F(xiàn)在為了更快的求出結(jié)果,命令當(dāng)然是越少越好。各個表的結(jié)構(gòu)如下:進(jìn)貨單jhd:jhdbh,jhrq進(jìn)貨單明細(xì)jhdmx:jhdbh,yclbh,jhsl領(lǐng)貨單lhd:lhdbh,lhrq領(lǐng)貨單明細(xì)lhdmx:lhdbh,yclbh,lhsl報(bào)廢單bfd:bfdbh,bfrq才艮廢單明細(xì)bfdmx:bfdbh,yclbh,bfsl退貨單thd:thdbh,thrq退貨單
54、明細(xì)thdmx:thdbh,yclbh,thsl原材料表yclb:yclbh,yclmc,yclgg查詢?nèi)掌诜秶旁赽egindata,enddata里為簡便起見,只計(jì)算進(jìn)貨和退貨,其它的照樣做就行了。Selectyclbh,sum(jhsl)asjhsl,100000.00-100000.00asthsl;Fromjhdjoinjhdmx;Onjhd.jhdbh=jhdmx.jhdbh;Wherebetween(jhd.jhrq,begindata,enddata);Groupbyyclbh;Union;Selectyclbh,100000.00-100000.00,sum(thsl);Fr
55、omthdjointhdmx;Onthd.thdbh=thdmx.thdbh;Wherebetween(thd.thrq,begindata,enddata);Groupbyyclbh;Intocursortemp1這樣就會產(chǎn)生這樣的結(jié)果yclbhjhslthsl00001343200000242340這些是第一節(jié)select產(chǎn)生的.00002034230000304234這些是第二節(jié)select產(chǎn)生的現(xiàn)在再對臨時(shí)表temp1進(jìn)行一次合計(jì)selectyclbh,sum(jhsl)asjhsl,sum(thsl)asthsl;fromtemp1;groupbyyclbh;intocursorte
56、mp2這個temp2就是結(jié)果了。注1:如果要計(jì)算四種操作的話,就再加多兩節(jié)select就行了。注2:在命令里使用100000.00-100000.00這樣奇怪的表達(dá)式是因?yàn)閟elect對那些要計(jì)算的、事先不能確定長度和類型的字段,它是根據(jù)運(yùn)算過程中產(chǎn)生的第一條記錄中,該字段的值來確定這個字段的類型和長度。所以以上那條命令,第一個記錄中thsl它是不知道長度是多少的,如果直接用0的話,那它就以為這個字段是數(shù)值型,長度是1,沒有小數(shù)位。這當(dāng)然不行,所以就要用這樣一個表達(dá)式,來使它知道這個字段有9位長,小數(shù)位是2。示例一.快速排名次考試排名次,一般有個要求,就是如果有兩個人并列第一,那跟著的就不是第
57、二名,而是第三名,即第二名跳空了。所以我想出以下這個方法。面對大數(shù)據(jù)量的排名次,若用scan.endscan或dowhile這種方法,時(shí)間會非常長。1048576個記錄中花了十多分鐘才排了四十多萬條記錄。而我這種方法只需九十多秒(硬件:PII300(100*3),128MPC100,5.1G,VFP5.0),方法如下:1。數(shù)據(jù)庫dele:rec_idc(7)升序;namec(10);fsn(4,1)降序;rec_orden(7),文件大小為29M,索引文件16M2。建一個視圖dele1SELECTDele.fs,Dele.rec_orde;FROMdele;ORDERBYDele.fsDESC3。根據(jù)視圖dele1建立視圖dele2SELECTDISTINCTDele1.fs,MIN(Dele1.rec_orde)ASrec_orde;FROMdele1;GR
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 1000道乘除法練習(xí)題讓數(shù)學(xué)更簡單
- 創(chuàng)新創(chuàng)業(yè)寵物店計(jì)劃書
- 電動觀光車租賃合同
- 2025年公務(wù)車輛互借合同
- 2025年農(nóng)村集體土地流轉(zhuǎn)合同標(biāo)準(zhǔn)
- 2025年醫(yī)療器械采購合法合同協(xié)議書范例
- 2025年二手車輛貸款合同模板
- 2025年共同策劃房地產(chǎn)合作開發(fā)項(xiàng)目合同書范本
- 2025年公共園林養(yǎng)護(hù)服務(wù)合同范本
- 2025年勞動合同策劃違約金賠償協(xié)議書
- 《我的家族史》課件
- 干部考察報(bào)告表()
- 02S404給排水圖集標(biāo)準(zhǔn)
- 湖北省技能高考機(jī)械類模擬試題
- 六年級勞動與技術(shù)下冊《課程綱要》
- 高空作業(yè)安全方案及應(yīng)急預(yù)案
- 關(guān)于與旅游發(fā)展集團(tuán)成立合資公司的可行性研究報(bào)告
- 第一部分-氣排球運(yùn)動介紹課件
- 世界局勢與主再來課件
- 思維游戲(小孩都喜歡玩的游戲)教學(xué)內(nèi)容課件
- 儲能技術(shù)課后參考答案梅生偉
評論
0/150
提交評論