數據庫--關係代數

基本運算

每一種基本運算的結果都是一個新的關係,可以用這個關係繼續參與運算,藉此便可進行復雜的運算

  • 選擇運算(select)==>相當於SQL語句中的WHERE子句的職能

    • 格式:σ選擇謂詞(關係)

    • 舉個栗子:
      • σSAL>1000(EMP)

      • 上式表示取出查詢工資大於1000的所有員工的信息

      • 等價於下面的SQL語句

      SELECT *
      FROM EMP
      WHERE SAL > 1000
      
    • 選擇謂詞的分類
      • 比較:=、≠、<、≤、>和≥
      • 連詞:and(∧)、or(∨)和not(¬)==>可以將多個謂詞合併成一個大的謂詞
      • 可以包括兩個屬性(字段的比較):σCOMM>SAL(EMP)表示抽成大於工資的人
  • 投影運算(project)==>相當於SQL語句中的SELECT子句的職能

    • 格式:∏字段序列(關係)

    • 舉個栗子
      • ∏ENAME,SAL(EMP)

      • 上式表示查看所有員工的姓名和工資

      • 等價於下面的SQL語句

      SELECT ENAME, SAL
      FROM EMP
      
  • 關係的組合運算==>就像SQL中select、where子句那樣的組合效果

    • 舉個栗子
      • ∏ENAME,SAL(σSAL>1000(EMP))

      • 上面的式子求出了所有工資大於1000的員工的名字和工資(實際上就是將σSAL>1000(EMP)執行的結果當做一個臨時的關係,參與了投影運算得到的)

      • 等價於下面的SQL語句

      SELECT ENAME, SAL
      FROM EMP
      WHERE SAL > 1000
      
    • 事實關係的組合運算就是那麼簡單,分析的時候把每個簡單運算的結果當做一個新的關係參與後面的運算,這樣一層層剝開來,再複雜的語句也變得容易分析
  • 並運算(union)==>相當於SQL中UNION關鍵字的職能

    • 格式:(關係r)∪(關係s)

    • 舉個栗子
      • ∏ENAME,SAL(σSAL>1000(EMP)) ∪ ∏ENAME,SAL(σCOMM>300(EMP))

      • 上面的式子求出了所有工資大於1000或抽成大於300的員工的姓名和工資,等價於下面的SQL語句

      SELECT ENAME, SAL
      FROM EMP
      WHERE SAL > 1000
      UNION
      SELECT ENAME, SAL
      FROM EMP
      WHERE COMM > 300
      
    • 幾點需要額外注意的
      • 此處的並運算是集合運算,所以結果是去重的,結果集中不存在重複的元組(而在SQL語句中,指定UNION ALL是可以保留重複的

      • 關係r與關係s必須是同元的,即它們的屬性的數目要求必須相同(這就和SQL語句中UNION使用的時候要求上下兩個語句的字段數相同是一樣的意思)

      • 關係r和關係s對應位置的屬性域應該是類型兼容的(同樣和SQL中UNION使用時,每個對應位置字段類型兼容是一樣的意思)

  • 集合的差運算(set-defference)==>相當於SQL語句中的EXCEPT

    • 格式:(關係r)-(關係s)

    • 舉個栗子
      • ∏ENAME,SAL(σSAL>1000(EMP)) - ∏ENAME,SAL(σCOMM>300(EMP))
      • 上面的式子表示工資大於1000但抽成不大於300的員工的姓名和工資,等價於下面的SQL語句
      SELECT ENAME, SAL
      FROM EMP
      WHERE SAL > 1000
      EXCEPT
      SELECT ENAME, SAL
      FROM EMP
      WHERE COMM > 300
      
    • 幾點需要額外注意的
      • 此處的注意同上面的並運算的注意事項
  • 笛卡爾積運算(Cartesian-product)==>等價於SQL語句中兩個表進行笛卡爾積(全匹配)得到的結果,即SQL中進行多表連接時不指定連接條件的情況

    • 格式:(關係r)×(關係)

    • 舉個栗子:
      • EMP × DEPT
      • 上面的式子表示兩個表進行全匹配,等價於下面的SQL語句
      SELECT *
      FROM EMP, DEPT
      
    • 下面兩個式子是等價的
      • ∏ENAME,DNAME(σEMP.DEPTNO=DEPT.DEPTNO(σJOB="MANAGER"(EMP×DEPT)))
      • ∏ENAME,DNAME(σEMP.DEPTNO=DEPT.DEPTNO((σJOB="MANAGER"(EMP))×DEPT)
      • 下面是對這兩個式子的SQL轉化,轉化之後就一目瞭然了
        -- 對應第一個式子
        SELECT ENAME, DNAME
        FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO
        WHERE JOB = 'MANAGER'
        
        -- 對應第二個式子
        SELECT ENAME, DNAME
        FROM DEPT JOIN (SELECT *
                        FROM EMP
                        WHERE JOB = 'MANAGER')
                  ON EMP.DEPTNO = DEPT.DEPTNO
        
  • 更名運算(rename)==>等價於SQL語句中as的職能

    • 格式:ρX(A1,A2,...,An)(E)==>表示的是將關係E更名爲X,Ai表示的是給E的第i個字段指定別名

    • 舉個栗子
      • ∏ENAME,DNAME(σe.DEPTNO=d.DEPTNO(σJOB="MANAGER"(ρe(EMP)×ρd(DEPT))))
      • 上面式子含義就不解釋了,是上面舉的栗子,只是引入了更名運算符,它等價於下面的SQL語句
      SELECT ENAME, DNAME
      FROM EMP e JOIN DEPT d ON e.DEPTNO = d.DEPTNO
      WHERE JOB = 'MANAGER'
      
  • 來,學習完上面的基本運算,來做個實際的栗子,要求找到員工表中的最高工資(因爲目前還沒有介紹類似SQL中組函數的操作,後面會介紹。所以通過以下方式來實現)

    • step1: 找到所有不是最高工資的人
      • ∏e1.SAL(σe1.sal < e2.sal(ρe1(EMP)×ρe2(EMP)))
    • step2: 用所有的員工減去上面的員工,即得到最高工資
      • ∏SAL(EMP) - ∏e1.SAL(σe1.sal < e2.sal(ρe1(EMP)×ρe2(EMP)))
  • 在書寫關係運算表達式的時候可以用序列號代替字段名(但是不直觀,不常用,一般不用)

    • 舉個栗子
      • ∏$6(σ$6 < $14(EMP×EMP))
      • 等價於下面的運算
      • ∏e1.SAL(σe1.sal < e2.sal(ρe1(EMP)×ρe2(EMP)))

附加運算

附加運算是由基本運算組成的,不能增強基本運算的運算能力,但是能簡化運算

  • 集合交運算(intersection)==>相當於SQL語句中INTERSECT關鍵字的職能

    • 格式:(關係r)∩(關係s)

    • 因爲集合交運算是可以由前面的基本運算組合產生的,所以把它歸到附加運算
      • A ∩ B <=> A - (A - B)
    • 舉個栗子
      • ∏ENAME,SAL(σSAL>1000(EMP)) ∩ ∏ENAME,SAL(σCOMM>300(EMP))
      • 上面的式子表示工資大於1000並且抽成大於300的員工的姓名和工資,等價於下面的SQL語句
      SELECT ENAME, SAL
      FROM EMP
      WHERE SAL > 1000
      INTERSECT
      SELECT ENAME, SAL
      FROM EMP
      WHERE COMM > 300
      
  • 自然連接(natural join)==> 相當於SQL語句中的NATURAL JOIN

    • 格式:(關係)⋈(關係)

    • 自然連接的形式化定義

      • r,s是兩個關係
      • R,S是上面兩個關係對應的關係模式(其實就是上述兩個關係各自的屬性列表)
      • R ∩ S 表示r和s的同名屬性列表
      • R ∪ S 表示出現在r或s上的屬性名列表(是一個集合,不包同名屬性,存在同名屬性會去重)
      • R - S 表示出現在R上,但不出現在S上的屬性名列表
      • 則可做如下定義
      • r⋈s = ∏R∪S(σr.A1=s.A1 ∧ r.A2=s.A2 ∧ ... ∧ r.An=s.An(r×s)) ,其中 R∩S={A1, A2, ..., An}
    • 舉個栗子
      • ∏name, course_id(instructor ⋈ teaches)
      • 上面的式子列出了所有老師的名字以及其所授課程的id,等價於下面的SQL語句
      SELECT name, course_id
      FROM intructor natural join teaches
      

    ps: 兩個關係模式執行自然連接以後屬性的排布順序:

    • 排在最前面的是兩個關係模式相同的屬性
    • 其次是隻屬於第一個關係模式的屬性
    • 最後是隻屬於第二個關係模式的屬性

    !!!所以所兩個關係模式進行自然連接以後,總的屬性的個數是減少了,具體減少的個數等於同名屬性的個數

  • theta連接==>是帶限定條件的笛卡爾積

    • 格式:(關係)⋈Θ(關係)

    • 形式化定義:
      • r ⋈Θ s = σΘ(r × s)
    • 舉個栗子
      • ∏name, course_id(instructor ⋈instructor.ID = teaches.ID ∧ instructor.salary > 5000 teaches)
      • 上面的式子表示列出所有工資大於5000的老師的名字以及其所授課程的id, 等價於下面的SQL語句
      -- 使用 join...on 的時候 on 後面寫連接條件,然後將其它條件放在where裏
      SELECT name, course_id
      FROM instructor join teaches on instructor.ID = teaches.ID
      WHERE instructor.salary > 5000     
      
  • 除運算(division)

    這個在書上沒講,是老師上課的時候補充的

    • 格式:(關係)÷(關係)

    • 形式化定義:
      R÷S = ∏R∪S( ( ∏R-S(r) × S ) - ∏R-S, S(r) )
    • 解釋起來挺麻煩的,這邊給出一個博客鏈接:點我
  • 賦值運算

    就是將一個關係表達式的結果賦值取一個臨時的名字,就相當於定義了一個臨時關係。這個操作就相當於SQL中with語句的職能

    • 格式: temp_name ← 關係表達式

    • 舉個栗子:
      temp1 ← R × S
      temp2 ← σr.A1=s.A1 ∧ r.A2=s.A2 ∧ ... ∧ r.An=s.An(temp1)
      result = ∏R∪S(temp2)
    • 上面的式子等價於: result = r⋈s
  • 外連接運算

    • 左外連:⟕
    • 右外連:⟖
    • 全外連:⟗

擴展運算

擴展運算是不能用基本的關係代數運算來實現的一類查詢,可以滿足複雜的查詢需求

  • 廣義投影(Generalized-projection)

    與基本運算中的投影運算相比,就是多了允許在選擇列表中出現表達式(在基本運算中的投影的選擇列表中只能出現字段)

    • 格式:∏F1, F2, ... , Fn(E)

      • 其中F1, F2, ... , Fn可以是字段或者是表達式
      • E代表一個關係
    • 舉個栗子:
      • ∏name, sal * 1.2(instructor)

      • 上面的式子表示查出所有老師的名字,以及漲了20%以後的工資,等價於下面的SQL語句

      SELECT name, sal * 1.2
      FROM instructor
      
  • 聚集函數(Aggregation function)

    聚集函數的符號表示是用書寫體G,這邊就直接用G指代了

    聚集函數是輸入值的一個匯聚,以多個值作爲輸入,將一個單一的值作爲返回結果

    多重集:使用聚集函數對其進行操作的彙集中,一個值可以出現多次,值出現的順序是無關緊要的。這樣的彙集稱爲多重集(就比方說統計一個員工表中員工的數量,然後我們通過統計員工的名字來統計,即便是同名的員工我們也是計算的)

    • 格式: G1, G2, ... , GnGF1(A1), F2(A2), ..., Fn(An)(E)

      • 其中前面的G1, G2, ... , Gn表示的是分組條件
      • 後面的F1(A1), F2(A2), ..., Fn(An)是聚集函數表達式列表
      • Fi(i = 1, 2, ..., n)表示聚集函數:sum、count、average、max、min
      • A1, A2, ... , An代表字段
    • 舉個栗子:
      • A1, A2Gsum(A3)(∏A1, A2, ..., An(σP(r1×r2×...×rm)) )
      • 等價於下面的SQL語句
      SELECT A1, A2, sum(A3)
      FROM r1, r2, ..., rm
      WHERE P
      GROUP BY A1, A2
      
    • 上面的聚集函數在進行計算的時候採用的都是多重集,也就是相同的值可以多次重複計算(也就是在執行聚集函數的時候是不去重計算),如果要去重計算的話就要採用下面的幾個函數寫法
      • sum_distinct
      • count_distinct
      • averag_distinct
      • max_distinct
      • min_distinct
    • 舉個栗子:
      • A1, A2Gsum_distinct(A3)(∏A1, A2, ..., An(σP(r1×r2×...×rm)) )
      • 上面的式子等價於下面的SQL語句
      SELECT A1, A2, sum(distinct A3)
      FROM r1, r2, ..., rm
      WHERE P
      GROUP BY A1, A2



作者:SunnyQjm
鏈接:https://www.jianshu.com/p/f7f9440e30a5
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章