2012-01-23 6 views
0

У меня проблема, которая сначала кажется простой, но на самом деле это не так. Я хранение слов в таблице таким образом, что пара строк «A B C D E» и «D E F» становится:Как подсчитать каждое слово в строке в цикле ORACLE?

id value 
-- ----- 
1 A 
1 B 
1 C 
1 D 
1 E 
2 D 
2 E 
2 F 

И я перейти к моей ORACLE процедуры строку, которая выглядит следующим образом: «A B C D G». И теперь я хочу проверить процентное сходство между строками в базе данных и строку, переданную как параметр.

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

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

id percentage 
-- ---------- 
1 80    -- 4 out of 5 letters exists in query string (A B C D) 
2 33    -- 1 out of 3 (D) 

Итак, мои вопросы:

  • что является наиболее эффективным способом, чтобы разделить строку запроса, а затем итерацию по нему (таблица ?)
  • как сохранить частичные результаты, а затем подсчитать их?
  • как считать итоговое процентное значение?

Каждая помощь была бы принята с благодарностью.

ответ

2

Следующий запрос предоставит вам то, что вы хотите, без необходимости беспокоиться о процедурах.

select id 
    , sum(case when value in ('A', 'B', 'C', 'D', G') then 1 else 0)/count(*) 
    from my_table 
group by id 

В качестве альтернативы, если вы иметь передать строку «ABCDG» и получить результат обратно вы можете сделать:

select id 
    , sum(case when instr('A B C D G', value) <> 0 then 1 else 0)/count(*) 
    from my_table 
group by id 

Эти действительно включают полное сканирование таблицы или индекса полное сканирование, если вам использовать предложенный показатель ниже, так что вы можете добавить следующий пункт где, если вы хотите, чтобы найти ids, которые имеют процент> 0.

select id 
    , sum(case when instr('A B C D G', value) <> 0 then 1 else 0)/count(*) 
    from my_table 
where exists (select 1 
        from my_table 
       where id = mt.id 
        and instr('A B C D G', value) <> 0) 
group by id 

Для всех запросов ваша таблица должна быть проиндексирована на my_table, id в этом порядке.

+0

Спасибо! Ваше решение очень помогло мне, это было совсем не то, что мне нужно, но это подтолкнуло меня в правильном направлении. В конце концов, мне придется использовать split, потому что мне нужно подсчитывать каждое значение любого значения, а не всю строку. Поэтому в моем случае я должен использовать что-то вроде: sum (случай, когда значение IN ('A', 'B', 'C', 'D', 'G'), затем 1 else 0)/count (*)
Итак, вся строка должна быть разделена:/ – Ziouas

+0

Ну, это работает, когда вы меняете порядок аргументов :) instr (value, 'ABCD G') не работает, но instr ('ABCD G', value) отлично работает , Спасибо, Бен! – Ziouas

+0

oops @ Ziouas, да ... извините, что привык писать его наоборот. Я отредактировал свой ответ, поэтому теперь он имеет больше смысла! – Ben

0

Вы имели в виду UTL_MATCH? Это не делает то, что вы пытаетесь достичь, но вы можете счесть это полезным, если определение вашего процентного соглашения не задано в камне.

+0

Вау, действительно хороший набор функций, но не моя цель.Сходство строк «A B» и «A C D B» должно быть 50% (2 точных совпадения), в этом алгоритме 72% (Jaro-Wnkler) или 43% (Edit Distance). Но я буду смотреть в будущее. Пальцы вверх! – Ziouas

Смежные вопросы