Соотнесение значений varchar - PullRequest
6 голосов
/ 26 июля 2011

Есть ли в Oracle 11 встроенный способ проверки корреляции значений в поле varchar2?Например, учитывая простую таблицу, такую ​​как эта:

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

Я хочу получить числовую индикацию, основанную на MEAL_NUM, CHEESE в паре в основном с PASTA и в меньшей степени с BEEF, CHICKEN и FISH.

Мое первое желание - использовать функцию CORR и преобразовать строки в число, возможно, либо предварительно перечислив их, либо выбрав rownum из уникального выбора.

Любые предложения, как это сделать?

Ответы [ 4 ]

3 голосов
/ 26 июля 2011

Вы не захотите использовать CORR - если вы создадите «номер еды» и назначите Beef = 1, Chicken = 2 и Pasta = 3, тогда коэффициент корреляции скажет, коррелирует ли увеличенный сыр сувеличено «количество еды».Но «число пищи», которое выше или ниже, ничего не значит, так как вы его придумали.Так что не используйте CORR, если ваши продукты на самом деле не заказаны, как цифры.

Статистика говорит об этом с уровнями измерения .На языке связанной статьи, 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

Предупреждение: возвращает неверные результаты, если вы включили ингредиент дважды в любой прием пищи.

Редактировать: Оказывается, вы не заинтересованы в сыре конкретно.Вы действительно хотите все пары "корреляций".Таким образом, мы можем абстрагировать «сыр» и назвать их только первым и вторым ингредиентами.Я добавил "возможный результат" к этому, который пытается вести себя как процентное соотношение еды, но не дает сильного результата, если ингредиентов очень мало.

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 голосов
/ 27 июля 2011

Сделайте самостоятельное объединение, чтобы получить все комбинации ингредиентов, а затем поправьте на два числа покушений

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

ОБНОВЛЕНИЕ: как Крис указываетвне, это не будет работать как есть.Я надеялся, что может быть какой-то способ отразить отображение от значения порядковый номер food_num до значения интервал (@Chris, спасибо за ссылку).Это может быть невозможно, и в этом случае этот ответ не поможет.

1 голос
/ 27 июля 2011

Попробуйте 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
0 голосов
/ 26 июля 2011

как насчет такого запроса?

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;

результатом должно быть количество времени, в течение которого каждый ингредиент делит еду_нума с СЫРОМ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...