官术网_书友最值得收藏!

1.5 表間關聯

顧名思義,表間關聯就是在多個表之間建立一種聯系。

例如,在之前所創建的“產品”“客戶”“訂單”這3個表中,“訂單”表中的每一個訂單都分別在“產品”表和“客戶”表中有對應的行。也就是說,每一個訂單都會對應一個產品和一個客戶。同樣,“產品”表或者“客戶”表中的每一行會在“訂單”表中有若干條的對應記錄(也就是訂單)。如果能夠在“產品”表與“訂單”表、“客戶”表與“訂單”表之間建立關聯,這些表就可以相互引用數據或者快速查閱關聯數據。

1.5.1 設置表間關聯

在【數據表】功能區的【表相關】功能組中,單擊【關聯】按鈕。彈出“表間關聯”對話框后,再單擊【增加】按鈕即可設置表間關聯,如下圖所示。

關于設置關聯的一些重要概念說明。

?父表與子表

在“編輯關聯”對話框中,左側用于設置父表及關聯列,右側用于設置子表及關聯列。那么,如何選擇父表和子表呢?

仍以“產品”表和“訂單”表為例。“訂單”表中的每一條記錄只能對應“產品”表中的一個產品(記錄),而每一個產品在“訂單”表中可能對應多個記錄(訂單),就像一個父親可以有多個兒子,而一個兒子只能有一個父親一樣,這種一對多的關系就稱為父子關系。很明顯,在“產品”表和“訂單”表之間建立關聯時,“產品”表是父表,“訂單”表是子表,它們通過“產品ID”列就可建立關聯。

在Foxtable中,這種父子關系的約束其實并不是很嚴格的。也就是說,子表中的一條記錄,也可以在父表中對應有多條記錄。例如,一個作者可以寫多本書,而一本書也可以有多個作者,不過實際應用時這種情況并不多見。

在上圖中,父表和子表是通過“產品ID”列進行關聯的。兩個表的關聯列名稱未必完全相同,僅僅是本例中“產品”和“訂單”表恰好都使用了相同的列名稱而已:假如將父表的“產品ID”列改為“產品編號”,那么就可以設置父表的“產品編號”列和子表的“產品ID”列進行關聯。盡管父表和子表的關聯列名稱可以不同,但其數據類型必須相同,且不能把表達式列作為關聯列使用。

關聯列數量不限,可根據需要隨意增加。一般建議關聯列的數量不要超過兩個。

?關聯選項

關聯設置對話框有兩個選項,分別是【同步更新關聯列內容】和【同步刪除關聯行】。

● 同步更新關聯列內容。

如果選中此復選框,在父表修改某行關聯列內容后,子表中對應行的關聯列內容會同步更新,使得兩個表之間的關聯行始終保持聯系。例如,“產品”表和“訂單”表通過“產品ID”建立了關聯,如果修改“產品”表中的“產品ID”,那么“訂單”表中相對應的“產品ID”也會自動作出修改。

● 同步刪除關聯行。

如果選中此復選框,在父表中刪除某行,在子表中對應的關聯行會同步刪除。例如,“產品”表和“訂單”表通過“產品ID”建立了關聯,如果在“產品”表中刪除某產品,那么“訂單”表中此產品的全部訂單也會被自動刪除。

?設置關聯名稱

由于這是一個新創建的表間關聯,單擊【確定】按鈕后,系統將提示輸入一個關聯名稱,以方便后期的使用和管理。這個名稱是自定義的,其命名規則和表名、列名完全一致,只要自己能夠準確地理解其語義即可。例如,產品的英文是“product”,訂單是“order”,可以簡單地將它們之間的關聯命名為“po”。表間關聯創建之后,系統會自動生成一個關聯表,如下圖所示。

其中,顯示在父表下方的“產品訂單”就是系統自動生成的關聯表,這個關聯表的名稱為父表標題和子表標題的兩者相連,因此顯示為“產品訂單”。此時,在“產品”表中單擊不同的記錄行時,關聯表會同步顯示與當前“產品ID”相關聯的訂單記錄。如上圖所示,由于父表中的“產品ID”為“P02”,因而關聯表就會從子表中調取與“P02”相關聯的全部訂單記錄并給予顯示。

?不同的關聯選項對管理表數據的影響

如果在創建關聯時,沒有選中【同步更新關聯列內容】復選框,那么在父表上對關聯列的任何修改都不會影響到子表。例如,將父表中的“P02”改為“A02”,這樣修改之后,由于子表沒有對應的“產品ID”為“A02”的記錄,因而關聯表不會有任何記錄顯示,如下圖所示。

如果在創建關聯時,選中【同步更新關聯列內容】復選框,那么在父表修改關聯列內容后,子表中相對應的關聯內容也會同步更新。例如,在父表中將“P02”改為“A02”,子表中的“P02”也將被同步更改為“A02”,這樣就可以使兩個表之間的關聯行始終保持聯系,如下圖所示。

需要注意的是,父表中的關聯列內容可以修改,但不能將其內容刪除,而且也無法刪除,子表則沒有此限制。例如,想將上圖父表中的“A02”單元格內容進行刪除是做不到的,只能進行修改,也就是內容不得為空。如果一定要刪除,只能刪除“A02”的所在行。

同樣地,在刪除父表中的數據行時,關聯表數據會受到【同步刪除關聯行】選項的影響。其原理與“同步更新關聯列內容”相同。

這里還要補充說明一點,由于關聯表數據是基于其他表的,在關聯表中對所做的任何修改都會同步體現到相對應的數據表中。例如,上圖關聯表中的“P02”都被改成了“A02”,而這個關聯表是基于“訂單”生成的,因而“訂單”表中的“P02”也都改成了“A02”,如下圖所示。

再如,在關聯表中增加行時,關聯列的內容會自動輸入,這個增加的行同樣會體現在其對應的數據表中。而且,這種自動輸入并不會受到是否選中【同步更新關聯列內容】復選框的影響。

如下圖所示,由于父表中的關聯列內容為“B02”,那么當在關聯表中新增數據行時,與其相關聯的“產品ID”列會自動填上“B02”;如果設置的關聯列有多個,則多個關聯列都會自動完成輸入。

假如父表和子表都有“產品ID”和“產品名稱”列,同時希望在關聯表新增行時,這兩列都能自動輸入,那么在建立父子關聯時,仍然只需選擇能唯一區分每一行的列(如“產品ID”),無需同時選擇“產品ID”和“產品名稱”列。如要實現“產品名稱”的自動輸入,可采用表達式列實現。

1.5.2 關聯表生成模式

在關聯設置窗口中,還可以設置關聯模式,如下圖所示。

關聯表有3種生成模式,分別為“單向”“雙向”“無”。現仍以“產品”表和“訂單”表的關聯為例。

?“單向”模式

此為默認模式。在單向生成模式下,“產品”表的底端會出現一個關聯表,標題為“產品訂單”;但“訂單”表的底端并不會出現關聯表。

如果希望在“訂單”表中單擊某個數據行,同樣可以查看該訂單所對應的產品資料時,可使用雙向模式。

?“雙向”模式

在雙向生成模式下,無論是父表還是子表,其下方都會出現一個關聯表。其中,父表下方的關聯表顯示的是子表數據,子表下方的關聯表顯示的是父表數據。

如下圖所示,當在“訂單”中單擊“產品ID”為“P05”的數據行時,關聯表會顯示與之對應的父表記錄。

關聯表的標題名稱變為“訂單產品”,它是通過子表標題與父表標題拼接而成的。

為了更清楚地看到雙向模式下的關聯表生成情況,再將“客戶”表和“訂單”表建立雙向關聯,并將其關聯名稱命名為“co”(c表示客戶“customer”,o表示訂單“order”),如下圖所示。

確定后就會發現,每個數據表的下方都會出現兩個關聯表,如下圖所示。

在上圖中,當在上方的“客戶”表中單擊不同的數據行時,下方的“客戶訂單”將顯示與之相關聯的訂單數據,這是因為“客戶”表與“訂單”表是父子關系,它們通過“客戶ID”列建立了關聯;當在下方的“客戶訂單”表中單擊不同數據行時,下方的“產品”表又會顯示與之相關聯的產品數據,這是因為關聯表“客戶訂單”是基于訂單表生成的,而“訂單”表與“產品”表又通過“產品ID”列建立了雙向關聯,如下圖所示。

由于“客戶訂單”表中所單擊的數據行“產品ID”的值為“P05”,因而這里的“產品”表顯示的就是與之相對應的數據記錄。

如果不喜歡這種關聯表的顯示方式(同樣的位置只能獨立顯示一個關聯表,查看其他關聯表時需單擊下面的表名稱切換),也可以在關聯表中單擊鼠標右鍵,選擇快捷菜單【停靠位置】→【獨立停靠】命令,這樣會更直觀一些(關于窗口停靠方面的知識將在下一章學習),如下圖所示。

由此可見,雙向生成模式可以為使用帶來很多便利,使得無論選擇哪一個表,所有相關的數據都可以信手拈來。再如,在“產品”表中,單擊任意一個產品,可看到與產品相關的所有訂單;單擊“訂單”中的任意一個訂單,又能立刻顯示與該訂單相關的客戶資料,如下圖所示。

同理,在“訂單”表中,單擊任意一個訂單,即可馬上看到與該訂單相關聯的產品和客戶信息,如下圖所示。

很顯然,如果將雙向改為單向,那么就只會在“產品”和“客戶”的下面生成兩個關聯表,“訂單”不會生成關聯表,也就無法做到雙向生成那樣的環環相扣、數據信手拈來。但是,雙向模式下,隨著關聯的增加,表的數量也會按平方數增長;若項目中產生太多表,就可能會影響到運行效率。

如上例,分別在“產品”表和“訂單”表之間、“客戶”表和“訂單”表之間建立兩個關聯,那么在雙向生成模式下,系統會產生2×3=6個關聯表,加上原來的3個數據表,合計就有9個表;而單向生成模式下只會產生兩個關聯表,加上原來的3個數據表,合計5個表,遠遠低于雙向生成的表數據量。假如以后再把數據表增加到5個、建立4個關聯,而這4個關聯都選擇了雙向生成,那么就將產生4×5=20個關聯表,加上原有的5個數據表,合計就有25個表,多么可怕!

當然,實際使用時是否開啟雙向生成完全根據自身的硬件性能及需求而定,只要不去濫用雙向生成就好。

?“無”模式

如果生成模式選擇“無”,那么不管是“產品”表和還是“訂單”表,底端都不會出現關聯表,這樣既不能在選擇某產品時查看訂購此產品的訂單,也不能在選擇某訂單時查看其對應產品的資料。

你也許會感到奇怪,既然如此,那還建立關聯干什么?

其實建立關聯,有時并不僅僅是為了方便查看關聯數據,更重要的是在關聯表之間相互進行數據的引用和計算。如果建立關聯的目的僅僅只是為了引用或統計數據,那么就直接將生成模式選擇為“無”吧!

1.5.3 多級關聯與同表關聯

?多級關聯

如果“表A”和“表B”建立了關聯,“表B”和“表C”建立了關聯,也就是A是B的父表,B又是C的父表,三者的關系類似于“父(表A) →子(表B) →孫(表C)”這樣的關系。

在雙向生成模式下,將生成6個關聯表,分別如下。

“表A”生成兩個關聯表:“表A表B”、“表A表B表C”。

“表B”生成兩個關聯表:“表B表A”、“表B表C”。

“表C”生成兩個關聯表:“表C表B”、“表C表B表A”。

在單向生成模式下,將生成3個關聯表,分別如下。

“表A”生成兩個關聯表:“表A表B”、“表A表B表C”。

“表B”生成一個關聯表:“表B表C”。

“表C”不生成任何關聯表。

由此可見,單向生成并非每個關聯只生成一個關聯表,而是按照“父 → 子 → 孫”這樣的路徑逐級生成;而雙向生成除了這條路徑外,還多了反向的“孫 → 子 → 父”的路徑,所以生成的關聯表數量至少要翻倍。

?同表關聯

表間關聯一般是將兩個不同的表通過關聯列聯系起來。在實際建立關聯時,父表和子表也可以是同一個表,這就是“同表關聯”。使用同表關聯時需要注意以下幾點。

第一,雙向生成對于同表關聯無效,即使選擇雙向生成,Foxtable還是會按照單向生成模式生成關聯表。

第二,建立同表關聯時父表和子表的關聯列必須不同。

例如,有一個“員工表”,其中有一列名為“上級”,用于輸入此員工的直接上司的姓名;另有一列為“姓名”列,用于輸入全部員工的姓名(包括所有的上級)。

現在新建一個關聯,父表為“員工表”,關聯列為“姓名”;子表同樣是“員工表”,關聯列為“上級”,這樣在單擊某個員工時會自動列出此員工的所有直接下屬,如下圖所示。

但是,如果在父表中單擊除姓名為“王兵”以外的其他行時,關聯表內容都為空。這是因為,其他員工姓名沒有出現在“上級”列中。

同表關聯在實際工作中極少用到,了解即可。

1.5.4 關聯表的數據引用與統計

仍以之前的“產品”“客戶”和“訂單”表為例。假如已經創建了兩個關聯:一個是“產品”與“訂單”通過“產品ID”列建立的關聯,關聯名稱為“po”;另一個是“客戶”與“訂單”通過“客戶ID”列建立的關聯,關聯名稱為“co”。由于這里的關聯僅僅用于不同表之間的數據引用和統計,因此在建立以上兩個關聯時,生成關聯表的模式選擇為“無”。

?引用父表數據

在“po”和“co”兩個關聯中,“訂單”表都是作為子表出現的。在這個表中,不論是“產品ID”還是“客戶ID”,都只能顯示具體的ID號。如果要在此表中同時顯示具體的產品名稱或客戶名稱,就可以通過引用父表數據的方法實現。

首先,在“訂單”表中添加一個表達式列,列名為“產品名稱”,然后編輯列表達式,如下圖所示。

在該生成器對話框中,可選擇的表有3個:一個是“訂單”,也就是當前表;另外兩個分別是“Parent(po)”和“Parent(co)”,也就是與當前表存在關聯關系的兩個父表。其中,“Parent(po)”表示產品表(關聯名稱為po),“Parent(co)”表示客戶表(關聯名稱為co)。

由于要引用“產品”表中的數據,因而這里就選擇“Parent(po)”。選擇該父表后,列表框將顯示該表中的所有列名稱,如下圖所示。

如果要引用該表中的“產品名稱”數據,只需雙擊“Parent(po)產品名稱”即可。

表達式設置完成后單擊【確定】按鈕,“訂單”表將自動增加一個表達式列“產品名稱”,該列的內容就取自產品表中的“產品名稱”。同理,再增加一個表達式列“客戶名稱”,其內容取自客戶表的“客戶名稱”列,如下圖所示。

如此一來,“訂單”表不僅能顯示“產品ID”“客戶ID”,也能同時顯示它們對應的“產品名稱”和“客戶名稱”了。

在引用父表數據時,如果當前表只有一個父表,列表達式可以簡寫為“Parent產品名稱”或“Parent客戶名稱”。由于本例的訂單表存在兩個父表,因此“po”或“co”是不能省略的,必須通過關聯名稱來指定從哪個父表中引用數據。

此外,對于這種父表與子表之間的數據引用,父子之間必須是嚴格的一對多關系。理由很明顯,如果不是一對多的關系,而是多對多的關系,那么子表在引用數據時,就不知道該引用父表中哪一條記錄的數據了,從而導致錯誤。

?統計子表數據

假如想在父表中統計相關聯的子表數據,也是一樣的處理方法。例如,現在想在“產品”表中統計不同產品的銷售數量,可以在“產品”表中增加一個名稱為“數量”的表達式列,如下圖所示。

需注意,這里的表達式使用了聚合函數Sum,表示對指定的列求和:Sum(Child(po)數量)。這里的Child表示的是子表。

由于“產品”表只有一個子表,因此,該表達式也可以簡寫為“Sum(Child數量)”。

用同樣的方法,也可以再增加一個“金額”表達式列,對子表中的“金額”進行統計。統計結果如下圖所示。

列表達式可用的其他聚合函數還有Avg(平均)、Min(最小值)、Max(最大值)、Count (計數)、St Dev(標準偏差)、Var(方差),如在“客戶”表中再增加下圖所示的列表達式。

上圖中所有的表達式列都是新增的,列表達式在右側。執行后的效果如下圖所示。

必須說明的是,通過聚合函數統計子表數據,只能是無條件的。但在實際工作中,有條件的統計非常普遍,怎樣才能實現條件統計呢?這就需要采取一種變通的方法。

比如,“訂單”表中有個用于記錄“是否付款”的邏輯列,已付款的為True,未付款的為False。如果想在“產品”表中統計“已付款”和“未付款”的訂單金額,就可以先在“訂單”表中增加一個表達式列“已付款金額”,此列可作為統計過渡列使用。其表達式為:

IIF([是否付款] = True,[金額],Null)

也可簡寫為:

IIF([是否付款],[金額],Null)

執行后的效果如下圖所示(如覺得此過渡列在“訂單”表中顯得多余,可將其隱藏)。

然后再在“產品”表中增加兩個表達式列對此過渡列進行統計。這兩個表達式列一個是“已付款金額”,一個是“未付款金額”。它們的表達式分別為:

Sum(Child(po).已付款金額)

Sum(Child(po).金額) - Sum(Child(po).已付款金額)

執行效果如下圖所示。

是不是覺得有點麻煩且不太方便?確實如此,畢竟表達式所支持的函數有限,而且限制比較多,對于一些較為復雜的統計要求,有時會顯得無能為力。

其實,Foxtable有兩種方式來實現計算和統計:一種是利用剛才的表達式;另一種就是利用代碼。表達式使用簡單,計算速度快,即使10萬行的計算也可以瞬間完成,而且不占據存儲空間,僅僅在運行時生成計算結果;而用代碼計算具備無比的靈活性,可以隨心所欲,只要代碼寫得合理,運行速度一樣快捷,但這就需要用到編程知識了。

關于編程,這是Foxtable作為開發平臺使用時才用到的知識,本書第2篇將專門學習。

主站蜘蛛池模板: 开原市| 营口市| 香格里拉县| 城步| 富宁县| 沙河市| 玉屏| 泗洪县| 启东市| 四平市| 通许县| 梁山县| 黑河市| 江源县| 高邑县| 根河市| 卓资县| 宜宾市| 余姚市| 安龙县| 淄博市| 天全县| 阜新市| 郓城县| 桦甸市| 江安县| 军事| 忻城县| 婺源县| 宝兴县| 潞城市| 灵山县| 新龙县| 泾阳县| 兰西县| 长乐市| 台北市| 龙游县| 石首市| 大荔县| 内江市|