閱讀565 返回首頁    go 魔獸


【數據蔣堂】第20期:從SQL語法看離散性

所謂離散性,是指集合的成員可以遊離在集合之外存在並參與運算,遊離成員還可以再組成新的集合。從離散性的解釋上可以知道,離散性是針對集合而言的一種能力,離開集合概念單獨談離散性就沒有意義了。

離散性是個很簡單的特性,幾乎所有支持結構(對象)的高級語言都天然支持,比如我們用Java時都可以把數組成員取出來單獨計算,也可以再次組成新的數組進行集合運算(不過Java幾乎沒有提供集合運算類庫)。

但是SQL的離散性卻很差。

SQL體係中有記錄的概念,但並沒有顯式的記錄數據類型。單條記錄被SQL作為隻有一條記錄的臨時表處理,也就是個單成員的集合。而且,SQL從表(集合)中取出記錄時總是複製出一條新記錄,和原表中的記錄已經沒有關係了,這個特性被稱為immutable。immutable特性有助於保證代碼的正確性和簡單性,但也會喪失離散性。

缺失離散性會帶來代碼的繁瑣和效率的低下。

比如要計算張三和李四的年齡差和工資差,SQL要寫成兩句:


SELECT (SELECT age FROM employee WHERE name='張三') - ( SELECT age FROM employee WHERE name='李四') FROM dual

SELECT (SELECT salary FROM employee WHERE name='張三') - ( SELECT salary FROM employee WHERE name='李四') FROM dual

這不僅書寫麻煩,而且要重複查詢。

如果支持較好的離散性,我們可以寫成這樣:


a = employee.select@1(name="張三")

b = employee.select@1(name="李四")

agediff=a.age-b.age

salarydiff=a.salary-b.salary

查詢結果可以遊離在集合外獨立存在,並可以反複使用。

immutable特性會要求每次運算都複製數據,這在隻讀的運算中還隻是浪費時間和空間影響效率,但如果要改寫數據時,造成的麻煩就嚴重得多。

比如我們想對業績在前10%銷售員再給予5%的獎勵。一個正常思路是先把業績在前10%的銷售員找出來,形成一個中間集合,然後再針對這個集合的成員執行獎勵5%的動作。但由於SQL缺乏離散性,immutable特性導致滿足條件的記錄再形成的集合和原記錄是無關的,在中間結果集上做修改沒有意義。這樣就迫使我們要把整個動作寫成一個語句,直接在原表中找到滿足條件的記錄再加以修改,而前10%這種條件並不容易簡單地在WHERE子句中寫出來,這又會導致複雜的子查詢。這還隻是個簡單例子,現實應用中比這複雜的條件比比皆是,用子查詢也很難寫出,經常采用的辦法則是先把滿足條件的記錄的主鍵計算出來,再用這些主鍵到原表中遍曆找到原記錄去修改,代碼繁瑣且效率極為低下。

如果語言支持離散性,我們就可以執行上述思路了:

a=sales.sort@z(amount).to(sales.len()*0.1)   //取出前業績在10%的記錄構成一個新集合

a.run(amount=amount*1.05)       //針對集合成員執行獎勵5%動作



從上麵兩個簡單例子可以看出,缺失離散性會加劇分步計算的困難,immutable特性會降低性能並占用空間。當然,離散性的問題還不止於此。

不能用原集合的成員構成新集合再進行計算,SQL在做分組時無法保持分組子集,必須強迫聚合,作為集合化語言,SQL的集合化並不徹底。沒有遊離記錄及其集合的表示方法,隻能用傳統的外鍵方案表示數據之間的關聯關係,寫出的代碼即繁瑣又難懂,而且運算性能還差,缺乏離散性的SQL無法采用直觀的引用機製描述關聯。特別地,沒有離散性的支持,SQL很難描述有序計算,有序計算是離散性和集合化的典型結合產物,成員的次序在集合中才有意義,這要求集合化,有序計算時又要將每個成員與相鄰成員區分開,會強調離散性。

這些具體內容我們會在後續文檔中逐步詳細說明。我們要從理論上改進SQL(或者更合適的說法是關係代數),主要工作就是在保持集合化的基礎上引入離散性,從而解決上述問題,讓新的語言能夠同時擁有SQL和Java的優點。

來源:數據蔣堂

最後更新:2017-08-29 11:32:25

  上一篇:go  人工智能升溫 機器視覺市場發展迅勐
  下一篇:go  空與非空 EMPTY_LOB和NULL的區別