2011-07-26 49 views
6

Oracle 11中是否有內置的方法來檢查varchar2字段中的值的相關性?例如,給定一個簡單的表像這樣:關聯varchar值

MEAL_NUM INGREDIENT 
-------------------- 
1   BEEF 
1   CHEESE 
1   PASTA 
2   CHEESE 
2   PASTA 
2   FISH 
3   CHEESE 
3   CHICKEN 

我想,基於MEAL_NUM數值指示,奶酪大多與麪食和與牛肉,雞肉和魚減輕度配對。

我的第一個傾向是使用CORR函數並將字符串轉換爲數字,可能是事先枚舉它們或從獨特的選擇中獲取rownum。

任何建議如何去做到這一點?

回答

0

這樣的查詢呢?

select t1.INGREDIENT, count(*)a 
from table t1, 
    (select meal_num 
     from table 
     where INGREDIENT = 'CHEESE') t2 
where t1.INGREDIENT <> 'CHEESE' 
and t1.meal_num=t2.mealnum 
group by t1.INGREDIENT; 

結果應該是每個成分與CHEESE共享meal_num的時間數。

3

你不會想要使用CORR - 如果你創建一個「食物編號」,並指定牛肉= 1,雞= 2,和麪食= 3,那麼相關係數會告訴你奶酪增加是否與增加相關「食物編號」。但是,「食物數量」越高或越低,並不意味着任何事情,因爲你做到了。所以,不要使用CORR,除非你的食物實際上是以某種方式訂購的,就像數字一樣。

統計學家對此的討論方式是levels of measurement。在鏈接文章的語言中,MEAL_NUM是一種名義上的衡量標準 - 或者如果這些飲食是按順序發生的話,也許是一種有序措施,但無論如何,使用相關係數是一個非常糟糕的主意。

你可能會想找到類似「什麼比例的牛肉餐也有奶酪?」以下將針對每種成分返回含有它的餐食的數量以及含有它的餐食和乾酪的數量。竅門是COUNT只能計算非空值。

SELECT Other.Ingredient, 
     COUNT(*) AS TotalMeals, 
     COUNT(Cheese.Ingredient) AS CheesyMeals 
    FROM table Other 
LEFT JOIN table Cheese 
     ON (Cheese.Ingredient = 'Cheese' 
     AND Cheese.Meal_Num = Other.Meal_Num) 
GROUP BY Other.Ingredient 

警告:如果您在任何一餐中包含成分兩次,則返回錯誤的結果。

編輯:事實證明,你並不特別對奶酪感興趣。你真的想要所有的「關聯」。所以,我們可以將「奶酪」抽象出來,並稱之爲第一和第二成分。我爲這個嘗試表現爲百分比膳食的「PossibleScore」添加了一個「PossibleScore」,但如果該配料的實例很少,則不會給出強大的分數。

SELECT First.Ingredient, 
     Second.Ingredient, 
     COUNT(*) AS MealsWithFirst, 
     COUNT(First.Ingredient) AS MealsWithBoth, 
     COUNT(First.Ingredient)/(COUNT(*) + 3) AS PossibleScore, 
    FROM table First 
LEFT JOIN table Second 
     ON (First.Meal_Num = Second.Meal_Num) 
GROUP BY First.Ingredient, Second.Ingredient 

當得分排序,這應該返回

PASTA CHEESE 2 2 0.400 
CHEESE PASTA  3 2 0.333 
BEEF  CHEESE 1 1 0.250 
BEEF  PASTA  1 1 0.250 
FISH  CHEESE 1 1 0.250 
FISH  PASTA  1 1 0.250 
CHICKEN CHEESE 1 1 0.250 
PASTA BEEF  2 1 0.200 
PASTA FISH  2 1 0.200 
CHEESE BEEF  3 1 0.167 
CHEESE FISH  3 1 0.167 
CHEESE CHICKEN 3 1 0.167 
+2

這是非常好的信息。我認爲OP想要使用像corr()這樣的函數的原因是,他可以將它應用於整個數據集,而不僅僅是一種成分。 –

+0

@James Oh;實際上這是一個很好的觀點。這是一個有趣的練習來概括我的「奶酪」表,以便它不一定稱爲「奶酪」,但我會等待聽到OP。 –

+0

是的,我打算讓這個東西在整個數據集上運行。 – owook

2

做一個自我加入由兩個meal_nums

SELECT t1.INGREDIENT, t2.INGREDIENT, CORR(t1.MEAL_NUM, t2.MEAL_NUM) 
FROM TheTable t1, TheTable t2 
WHERE t1.INGREDIENT < t2.INGREDIENT 
GROUP BY t1.INGREDIENT, t2.INGREDIENT 

應該給你把所有的在成分組合,然後科爾例如:

BEEF CHEESE 0.999 
BEEF PASTA 0.998 
CHEESE PASTA 0.977 

更新:正如克里斯指出的,這不會按原樣工作。我所希望的是,可能有某種方法可以將序號 meal_num映射到區間(@Chris,感謝您的鏈接)的值。這可能是不可能的,在這種情況下,這個答案不會有幫助。

+1

我很確定這是一個壞主意;如果牛肉出現在膳食2,3,4中,並且奶酪僅出現在膳食6中,那麼您將找到具有對(2,6),(3,6)和(4,6)的相關係數。這將是一個問題 - 點都在水平線上,相關係數會返回一些非常有趣的地方。 –

+0

更新:這不僅僅是誤報 - 我的統計數據有點生疏,但我認爲如果您將其數據作爲示例,相關係數應該返回除以零的誤差。如果你給「CORR」任何實際上不是數字的措施,你都在問各種麻煩。 –

+0

[這裏](http://en.wikipedia.org/wiki/Levels_of_measurement)是一個更具技術性的討論,我試圖用「數值量度」這個詞來說。 –

1

嘗試DBMS_FREQUENT_ITEMSET

--Create sample data 
create table meals(meal_num number, ingredient varchar2(10)); 

insert into meals 
select 1, 'BEEF' from dual union all 
select 1, 'CHEESE' from dual union all 
select 1, 'PASTA' from dual union all 
select 2, 'CHEESE' from dual union all 
select 2, 'PASTA' from dual union all 
select 2, 'FISH' from dual union all 
select 3, 'CHEESE' from dual union all 
select 3, 'CHICKEN' from dual; 

commit; 

--Create nested table type to hold results 
CREATE OR REPLACE TYPE fi_varchar_nt AS TABLE OF VARCHAR2(10); 
/

--Find the items most frequently combined with CHEESE. 
select bt.setid, nt.column_value, support occurances_of_itemset 
    ,length, total_tranx 
from 
(
    select 
     cast(itemset as fi_varchar_nt) itemset, rownum setid 
     ,support, length, total_tranx 
    from table(dbms_frequent_itemset.fi_transactional(
     tranx_cursor => cursor(select meal_num, ingredient from meals), 
     support_threshold => 0, 
     itemset_length_min => 2, 
     itemset_length_max => 2, 
     including_items => cursor(select 'CHEESE' from dual), 
     excluding_items => null)) 
) bt, 
table(bt.itemset) nt 
where column_value <> 'CHEESE' 
order by 3 desc; 


    SETID COLUMN_VAL OCCURANCES_OF_ITEMSET  LENGTH TOTAL_TRANX 
---------- ---------- --------------------- ---------- ----------- 
     4 PASTA       2   2   3 
     3 FISH       1   2   3 
     1 BEEF       1   2   3 
     2 CHICKEN      1   2   3