IT貓撲網(wǎng):您身邊最放心的安全下載站! 最新更新|軟件分類|軟件專題|手機(jī)版|論壇轉(zhuǎn)貼|軟件發(fā)布

您當(dāng)前所在位置: 首頁(yè)數(shù)據(jù)庫(kù)MSSQL → 數(shù)據(jù)庫(kù)理論:學(xué)習(xí)基于SQL數(shù)據(jù)庫(kù)的算法

數(shù)據(jù)庫(kù)理論:學(xué)習(xí)基于SQL數(shù)據(jù)庫(kù)的算法

時(shí)間:2015-06-28 00:00:00 來(lái)源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評(píng)論(0)

算法是計(jì)算機(jī)科學(xué)中一個(gè)重要的研究方向,是解決復(fù)雜問(wèn)題的關(guān)鍵。在計(jì)算機(jī)世界中,算法無(wú)處不在。數(shù)據(jù)庫(kù)是存儲(chǔ)數(shù)據(jù)和執(zhí)行大批量計(jì)算的場(chǎng)所,在數(shù)據(jù)庫(kù)中使用一些簡(jiǎn)單的SQL命令,進(jìn)行存儲(chǔ)、查詢、統(tǒng)計(jì)、以解決現(xiàn)實(shí)世界中的問(wèn)題已經(jīng)是屢見(jiàn)不鮮。隨著數(shù)據(jù)量的大幅度增加和業(yè)務(wù)規(guī)則的日益復(fù)雜,越來(lái)越需要一種專門(mén)的方法來(lái)滿足效率和準(zhǔn)確性方面的要求。如何把解決問(wèn)題的復(fù)雜算法轉(zhuǎn)換為數(shù)據(jù)庫(kù)能夠執(zhí)行的命令,也是數(shù)據(jù)庫(kù)應(yīng)用技術(shù)研究的一個(gè)方面。本文以MSSQL中的命令來(lái)闡述例子。

數(shù)據(jù)庫(kù)中可以存儲(chǔ)實(shí)體的數(shù)據(jù)集合,在進(jìn)行運(yùn)算時(shí),數(shù)據(jù)庫(kù)使用批量計(jì)算的方法來(lái)處理數(shù)據(jù),批量的從存儲(chǔ)設(shè)備上讀取數(shù)據(jù),處理之后又批量的寫(xiě)回存儲(chǔ)設(shè)備。有的數(shù)據(jù)庫(kù)提供了游標(biāo),游標(biāo)可以讀取出表中一行的數(shù)據(jù)中的每一個(gè)字段,對(duì)這些字段進(jìn)行復(fù)雜的業(yè)務(wù)規(guī)則計(jì)算,然后再寫(xiě)回?cái)?shù)據(jù)庫(kù)中。與使用批量的方法比較,批量計(jì)算的方法消耗的資源相對(duì)比較少,而使用游標(biāo)則占用太多的資源,速度比較慢,效率較低并且還有加鎖條件等許多的限制。

比如對(duì)于數(shù)據(jù)庫(kù)中存儲(chǔ)了學(xué)生成績(jī)student_Score(sno,cno,score,level),成績(jī)從0分到100分不等,如果需要在分?jǐn)?shù)的后面存儲(chǔ)一個(gè)字段字level來(lái)說(shuō)明成績(jī)的優(yōu)劣,90分以上的A,80-90分為B,60-80分的為C,60分以下的為D,以下有幾種算法都可以達(dá)到同樣的目標(biāo):

1.定義一個(gè)游標(biāo),選擇student_Score表中所有的成績(jī)記錄,定義一個(gè)存儲(chǔ)成績(jī)的變量@cur_score,存儲(chǔ)當(dāng)前紀(jì)錄的分?jǐn)?shù),定義一個(gè)存儲(chǔ)當(dāng)前分?jǐn)?shù)所在成績(jī)級(jí)別的變量@cur_level,用以存儲(chǔ)成績(jī)好壞的標(biāo)記。算法如下:如果游標(biāo)中的紀(jì)錄不為空,從游標(biāo)中取出當(dāng)前紀(jì)錄的成績(jī),判斷成績(jī)所在的分?jǐn)?shù)段,把結(jié)果存儲(chǔ)在變量@cur_level中,以@cur_level中的值更新當(dāng)前紀(jì)錄中的level字段。整個(gè)過(guò)程需要至少讀取數(shù)據(jù)庫(kù)兩次,一次為獲得紀(jì)錄,一次需要寫(xiě)入數(shù)據(jù)庫(kù),每條記錄都需要經(jīng)過(guò)這個(gè)過(guò)程,效率相對(duì)低。

2.依次批量更新數(shù)據(jù)庫(kù),把所有的level字段的值設(shè)置為D,再次更新數(shù)據(jù)庫(kù),把成績(jī)大于等于60的紀(jì)錄的Level字段更新為C,依次更新B、A。這樣做的一個(gè)缺點(diǎn)是有些紀(jì)錄的Level字段被更新多次,比如一個(gè)記錄最后的Level字段的值是A,則它首先被更新為D,依次被更新為C、B、A。這些重復(fù)的更新是可以被消除的,把算法改進(jìn)一下就可以省去重復(fù)更新的花費(fèi)。更新后的算法是這樣的,把成績(jī)介于0和60分的紀(jì)錄的Level字段更新為D,依次更新各個(gè)分?jǐn)?shù)段的成績(jī)。實(shí)現(xiàn)的這種算法的SQL語(yǔ)句并不難寫(xiě)出,使用Between…and…表達(dá)式即可以表達(dá)例如介于80到90之間紀(jì)錄的選擇條件。

3.鑒于第二種方法最后的分析,使用between…and…表達(dá)式同時(shí)參照一個(gè)表來(lái)更新紀(jì)錄,則可以方便表達(dá)分?jǐn)?shù)段與相應(yīng)的level信息,把這些信息存儲(chǔ)到一個(gè)表level_about中,在更新student_score表的過(guò)程中可以參照這個(gè)表。計(jì)算的過(guò)程中,需要把level_about表的內(nèi)容讀出來(lái),然后進(jìn)行計(jì)算。對(duì)于整個(gè)計(jì)算過(guò)程來(lái)說(shuō),犧牲空間和部分效率來(lái)?yè)Q來(lái)操作方便,,由于現(xiàn)在計(jì)算機(jī)的速度相當(dāng)快,level_about表占用的空間又很小,這方面的損失可以忽略不記。Level_about表中的信息至少包含3個(gè)字段:start_score,記錄起始分?jǐn)?shù),end_score記錄終止分?jǐn)?shù),level記錄介于起始分?jǐn)?shù)和終止分?jǐn)?shù)之間的分?jǐn)?shù)應(yīng)該得到的成績(jī)。表中的數(shù)據(jù)應(yīng)該類似于這樣:

Start_score End_score level
0 59 D
60 79 C
80 89 B
90 100 A
?
更新student_Score表中的紀(jì)錄需要依據(jù)Start_score和End_score來(lái)判斷當(dāng)前記錄中成績(jī)所在的Level,在MSSQL中實(shí)現(xiàn)的SQL語(yǔ)句:

Update student_score set student_score.level=level_about.level from
level_about where student.score between level_about.start_score and level_about.end_score
?
比較以上3種方法,實(shí)現(xiàn)同一個(gè)目的采用不同的算法實(shí)現(xiàn)的效果是不同的。

一些簡(jiǎn)單的算法不需要經(jīng)過(guò)修改就可以直接應(yīng)用到數(shù)據(jù)庫(kù)中,比如業(yè)務(wù)需要每天晚上都需要結(jié)算一天的情況,一周兩次自動(dòng)結(jié)算獎(jiǎng)金,結(jié)算獎(jiǎng)金時(shí)間在每周再周一和周四的晚上0點(diǎn)。為了實(shí)現(xiàn)系統(tǒng)的自動(dòng)結(jié)算,需要使用系統(tǒng)的任務(wù),給系統(tǒng)制訂一個(gè)作業(yè),指定每天晚上0點(diǎn)結(jié)算就可以實(shí)現(xiàn)系統(tǒng)的自動(dòng)結(jié)算(由于結(jié)算的時(shí)間間隔可能是會(huì)變化,不能使用作業(yè)中的定時(shí)功能)。為了可以在周一和周四結(jié)算,在數(shù)據(jù)庫(kù)中設(shè)置一個(gè)表misc,其中的字段相當(dāng)于全局變量,表中只有一條紀(jì)錄,使用其中的一個(gè)字段(days)來(lái)記錄當(dāng)前結(jié)算的次數(shù),也就是以系統(tǒng)開(kāi)始運(yùn)行為標(biāo)準(zhǔn)經(jīng)過(guò)的天數(shù)。系統(tǒng)執(zhí)行任務(wù)同時(shí)更新misc表中的days使其增長(zhǎng)update misc set days=days+1。

業(yè)務(wù)需求是每周一和周四結(jié)算獎(jiǎng)金,不難發(fā)現(xiàn)奇數(shù)次結(jié)算依次相差7天,偶數(shù)次結(jié)算依次相差7天,相鄰奇數(shù)次和偶數(shù)此結(jié)算相差3天,可以使用求余的方式來(lái)統(tǒng)一這個(gè)問(wèn)題。如果當(dāng)前天數(shù)(days)與7求余結(jié)果為0或者當(dāng)前天數(shù)(days)減去3之后求余的結(jié)果為0,則當(dāng)前天數(shù)是結(jié)算的日期。具體的實(shí)現(xiàn)的算法是:

1、提取當(dāng)前的天數(shù)到一個(gè)變量中declare @days int set @days=(select days from misc)

2、判斷是否滿足結(jié)算條件if @days%7=0 or (@days-3)%7=0 begin…end

類似于這樣簡(jiǎn)單的算法可以直接的應(yīng)用到數(shù)據(jù)庫(kù)中而不會(huì)發(fā)生問(wèn)題。

復(fù)雜的業(yè)務(wù)規(guī)則需要復(fù)雜的算法,復(fù)雜的規(guī)則對(duì)于一個(gè)有具體數(shù)字的變量來(lái)說(shuō),實(shí)現(xiàn)起來(lái)已經(jīng)比較復(fù)雜,如果應(yīng)用到數(shù)據(jù)庫(kù)中存儲(chǔ)的雜亂無(wú)章的一大批數(shù)字,并且實(shí)現(xiàn)批量的計(jì)算,則需要對(duì)算法進(jìn)行大幅度的調(diào)整。

比如業(yè)務(wù)規(guī)則需要在員工每4000元的獎(jiǎng)金中扣除400元作為重復(fù)消費(fèi),并且在扣除最后的400元,重復(fù)消費(fèi)一次獎(jiǎng)勵(lì)一件產(chǎn)品,需要在數(shù)據(jù)庫(kù)中使用一個(gè)表(award_repeat)記錄產(chǎn)生的重復(fù)消費(fèi)。如果一次扣除的獎(jiǎng)金不足400元,在下次結(jié)算的時(shí)候接著扣除,直到扣除的獎(jiǎng)金夠400元,然后獎(jiǎng)勵(lì)一件產(chǎn)品,進(jìn)入下次的循環(huán),比如現(xiàn)在獎(jiǎng)金總數(shù)達(dá)到了3600元,則不會(huì)扣除,如果達(dá)到了3700元,則要扣除100元,如果達(dá)到了7700元,則要扣除410元,并且產(chǎn)生一個(gè)重復(fù)消費(fèi)。

為了實(shí)現(xiàn)這個(gè)規(guī)則,在員工表(member)中記錄每個(gè)員工獎(jiǎng)金的總數(shù)([total_award]),同時(shí)記錄重復(fù)消費(fèi)的次數(shù)([repeat_num]),在另外的過(guò)渡表(award_day)中記錄每次的獎(jiǎng)金和每次扣除重復(fù)消費(fèi)的獎(jiǎng)金,最后在獎(jiǎng)金表(award)中綜合當(dāng)次獎(jiǎng)金和當(dāng)次結(jié)算需要扣除的重復(fù)消費(fèi)就得到了當(dāng)次結(jié)算實(shí)際發(fā)放的獎(jiǎng)金。采用批量的計(jì)算方法,實(shí)現(xiàn)的算法是:在計(jì)算獎(jiǎng)金之后,扣除重復(fù)消費(fèi)之前把當(dāng)前獎(jiǎng)金累加到員工的([total_award])字段([total_award]),記錄沒(méi)有扣除重復(fù)消費(fèi)的所有的獎(jiǎng)金總和。實(shí)現(xiàn)重復(fù)消費(fèi)計(jì)算的的算法是,設(shè)定條件(F1)為在member表中存在獎(jiǎng)金總數(shù)大于等于重復(fù)消費(fèi)次數(shù)加1后乘以4000,如果有滿足條件F1的記錄,則選擇滿足條件的紀(jì)錄中主鍵和當(dāng)前的日期(days)插入到重復(fù)消費(fèi)表(award_repeat)中,然后更新member表中滿足條件F1的repeat_num使其增加1,重復(fù)檢查條件F1,直到member表中沒(méi)有滿足條件F1紀(jì)錄。

結(jié)論:在數(shù)據(jù)庫(kù)中研究和實(shí)現(xiàn)算法有著相當(dāng)大的困難,同時(shí)也是一種挑戰(zhàn)。隨著現(xiàn)實(shí)世界中業(yè)務(wù)規(guī)則的日益復(fù)雜,相應(yīng)的數(shù)據(jù)庫(kù)應(yīng)用軟件實(shí)現(xiàn)業(yè)務(wù)規(guī)則需要的算法也日益復(fù)雜,把復(fù)雜的算法應(yīng)用在數(shù)據(jù)庫(kù)中需要找到一個(gè)統(tǒng)一的方式,在熟悉業(yè)務(wù)規(guī)則的前提下,根據(jù)數(shù)據(jù)庫(kù)的特點(diǎn)和相應(yīng)的執(zhí)行命令的能力,找到一種適合數(shù)據(jù)庫(kù)批量計(jì)算的步驟是解決問(wèn)題的關(guān)鍵。

關(guān)鍵詞標(biāo)簽:SQL數(shù)據(jù)庫(kù)

相關(guān)閱讀

文章評(píng)論
發(fā)表評(píng)論

熱門(mén)文章 淺談JSP JDBC來(lái)連接SQL Server 2005的方法 淺談JSP JDBC來(lái)連接SQL Server 2005的方法 SqlServer2005對(duì)現(xiàn)有數(shù)據(jù)進(jìn)行分區(qū)具體步驟 SqlServer2005對(duì)現(xiàn)有數(shù)據(jù)進(jìn)行分區(qū)具體步驟 sql server系統(tǒng)表?yè)p壞的解決方法 sql server系統(tǒng)表?yè)p壞的解決方法 MS-SQL2005服務(wù)器登錄名、角色、數(shù)據(jù)庫(kù)用戶、角色、架構(gòu)的關(guān)系 MS-SQL2005服務(wù)器登錄名、角色、數(shù)據(jù)庫(kù)用戶、角色、架構(gòu)的關(guān)系

相關(guān)下載

    人氣排行 配置和注冊(cè)O(shè)DBC數(shù)據(jù)源-odbc數(shù)據(jù)源配置教程 如何遠(yuǎn)程備份(還原)SQL2000數(shù)據(jù)庫(kù) SQL2000數(shù)據(jù)庫(kù)遠(yuǎn)程導(dǎo)入(導(dǎo)出)數(shù)據(jù) SQL2000和SQL2005數(shù)據(jù)庫(kù)服務(wù)端口查看或修改 修改Sql Server唯一約束教程 SQL Server 2005降級(jí)到2000的正確操作步驟 sql server系統(tǒng)表?yè)p壞的解決方法 淺談JSP JDBC來(lái)連接SQL Server 2005的方法