第36期:JOIN延伸:維度概念
談到數據分析時常常會用到維度這個詞,針對數據立方體的鉆取、旋轉、切片等操作都是圍繞維度進行的,幾乎所有的數據分析人員都知道并會運用這個術語,但要問及它的定義,卻幾乎沒有人能給出來。
通俗來講,我們把用來分類的屬性(字段)稱為維度,比如地區、年度、產品類型等;而另外一些用于聚合運算的屬性則稱為測度,比如銷售額、產量、考試成績等。維度不能做聚合運算,比如計算地區合計是沒有意義的;測度則不能用于分類,比如按銷售額分類也沒什么業務意義。我們通常就是用是否”可用于分類“來判定一個屬性是不是維度,但這其實只是對于維度性質的描述,并不能作為定義。
一
我們基于關系數據庫來討論這個問題,先簡單回顧一下基本概念。
設有一個關系數據庫,其中有若干數據表,表的數據結構由字段構成,表的數據由記錄構成。
數據表的某些字段被指定為主鍵,需要滿足這樣的條件:表中所有記錄在這些字段上的取值是互不相同的。也就是說,可以用主鍵值來***確定相應的記錄。數據表可以沒有主鍵,但有只能有一套。構成主鍵的字段稱為主鍵字段。
每個數據表可以有多套外鍵,外鍵也是該數據表的某些字段,其取值總是在另一個表(可能是本表)的主鍵取值范圍內。這里的另一個表被稱為外鍵指向表,簡稱外鍵表,構成外鍵的字段被稱為外鍵字段。
現在,我們定義:在關系數據庫中,不是外鍵字段的主鍵字段被稱為維度,維度所在的表稱為維表,維度可以用維表的主鍵字段來標識。順便地,我們定義即不是主鍵字段也不是外鍵字段的字段為測度。從這個定義上看,顯然不可能某個字段即是維度又是測度。
需要說明的是,我們這里所說的主鍵外鍵是指邏輯意義上的概念,也就是在數據的E-R結構設計中的主外鍵。有時為了性能而在物理數據結構中并不真地建立主鍵和外鍵,這種情況不在我們的考慮范圍內。
二
先從一些例子來理解維度的定義。
看這兩個同維表:
我們會在manager表建立外鍵,字段為id,指向employee表的主鍵id。這時,manage.id就即是主鍵字段也是外鍵字段,那么它不是維度。而employee.id是主鍵字段而不是外鍵字段,那么它就是維度。
再看主子表的情況:
OrderDetail.id是主鍵字段,但也是指向Orders表的外鍵字段,所以它不是維度。而Orders.id是主鍵字段但不是外鍵字段,那么它是維度,OrderDetail.no是主鍵字段且不是外鍵字段,它也是維度。
OrderDetail.no這個維度有些特殊,一般來說,不會有另外一個外鍵字段和它關聯了,我們把這種未被指向的維度稱為孤維。在查詢界面中做維度對齊運算時一般不用列出來孤維。
三
再來檢驗這個定義是否和常規的維度觀念相符,并且對于不相符的情況要給出合理的解決方案。
對于地區、產品這些常規維度,數據庫中都會有對應的地區表、產品表,那么這些維度就對應了這些表的主鍵字段,符合我們定義。而銷售額、產量等屬性則不可能對應到某個表的主鍵,所以確實也不是維度。
但日期(或年度)呢?它顯然是個維度,但數據庫中并沒有一個表以它為主鍵,似乎不符合我們的維度定義。
事實上,所有用到日期數據類型的數據庫在邏輯上都應當有一個日期表,其它數據表的日期型字段均可以視為指向這個日期表的外鍵。但由于日期的相關信息都可以由日期本身計算出來(年度、月份等),而沒有需要單獨存儲的屬性,因此我們通常不會在物理數據庫中建立這個日期表。那么,只要在邏輯上恢復這個日期表,日期就符合前面的維度定義了。我們把這種邏輯上應該有但物理上并未建立的表稱為假表,假表可以看成是一個單字段無記錄的表,這個單字段也就是該表的主鍵,這樣就可以承載沒有物理表的維度了。類似地,年度、月份也都可以用假表定義。
四
再觀察年齡這種屬性,它有可能用于分類(每個年齡的人數),又可能用于聚合(某部門人員的平均年齡),從性質上看,它似乎即是維度又是測度?這就與我們的定義相悖了。
其實,我們在用年齡分類統計時并不是用年齡值本身,而是年齡段,年齡本身應該是個實數值,這是不能用于分類的。也就是說,年齡是測度,而通過年齡計算出來的年齡段才是個維度。這時候,我們要引入維函數概念,維函數以某個字段值為參數,返回某個維度的取值。通過維函數可以把測度轉換成維度,在它的幫助下,我們就可以保持維度的嚴格定義,同時又不和常規觀念矛盾。
五
這里的維度定義是基于外鍵概念的,而我們知道,外鍵實際上定義了表之間的JOIN關系。從這個意義上講,維度是被JOIN定義的!