2016-11-01 4 views
1

Я пишу основную поисковую систему, идущую против внутреннего хранилища данных.Подсчет совпадений в Oracle

Предположим, у меня есть таблица «навыки», как это:

EmpID Skills 
----- -------------------- 
    1 ,Java, 
    2 ,Java,,C#, 
    3 ,C#,,Ruby, 
    4 ,Java,,C#,,Python, 
    5 ,Python,,C#, 

Мне нужно написать запрос, который ищет таблицу навыков, в поисках совпадений.

Если я ищу Java И C#, я хотел бы, чтобы эти результаты:

EmpID Skills    Matches 
----- ----------------- ------- 
    2 ,Java,,C#,    2 
    4 ,Java,,C#,,Python,  2 

Если я ищу Java ИЛИ C#, я хотел бы, чтобы эти результаты , по заказу Матчи:

EmpID Skills    Matches 
----- ------------------ ------- 
    2 ,Java,,C#,    2 
    4 ,Java,,C#,,Python,  2 
    1 ,Java,     1 
    3 ,C#,,Ruby,    1 
    5 ,Python,,C#,    1 

Как написать этот запрос в SQL (Oracle 11)?

Спасибо!

+0

Как вы планируете обеспечить «пользовательский ввод» (навыки, чтобы быть совпавшие, и выбор «ИЛИ» против «И» и т.д.?) Какой выбор похож на И и ИЛИ должны там быть доступны при вы вводите три навыка для поиска или четыре навыка? Просто количество навыков? – mathguy

+0

У нас есть предопределенный список навыков и показать их в списке с несколькими выборами. Пользователь также может установить флажок, чтобы сделать все необходимые навыки (И), или оставить его непроверенным (ИЛИ). – WOPR

+0

Ох - так что вы будете искать ВСЕ навыки, или ЛЮБЫЕ ОДНИ ИЗ навыков - не другие комбинации. Затем в представленном мной решении (которое работает для выбора OR, соответствие ANY ONE), вы можете получить версию AND (соответствие всем навыкам), добавив предложение WHERE во внешний выбор - выбирая только строки, в которых количество совпадений равна общему количеству навыков. – mathguy

ответ

2
with 
    test_data (empid, skills) as (
     select '1', ',Java,'    from dual union all 
     select '2', ',Java,,C#,'   from dual union all 
     select '3', ',C#,,Ruby,'   from dual union all 
     select '4', ',Java,,C#,,Python,' from dual union all 
     select '5', ',Python,,C#,'  from dual 
    ) 
-- end of test data; SOLUTION BEGINS BELOW 
select empid, skills, 
     case when skills like '%,Java,%' then 1 else 0 end + 
     case when skills like '%,C#,%' then 1 else 0 end as matches 
from test_data 
order by matches desc, empid -- ORDER BY is optional 
; 
+0

В зависимости от ваших требований и, мне нравится простота этого ответа. Если вам нужно, чтобы он был немного более надежным, рассмотрите простой REGEX. 'CASE WHEN REGEXP_INSTR (x, '(, | ^) Java (, | $)')> 0 THEN 1 ELSE 0 END'. Кроме того, чтобы использовать это в сценарии И, просто фильтруйте с помощью 'WHERE matches = 2'. –

+0

@HepC - в более надежной настройке (насколько это возможно, когда базовые данные даже не в первой нормальной форме), входы (навыки для поиска) будут указаны в вспомогательной таблице, и решение будет сделайте соединение вместо ручного счета ... но это еще одна история. – mathguy

+0

@HepC - регулярные строковые функции (LIKE, INSTR и т. Д.) Должны быть предпочтительнее регулярного выражения, когда это возможно - они быстрее. Кроме того, существует regexp_like, нет необходимости в regexp_instr, и совпадающий шаблон может быть намного проще - в настройке OP все жетоны ALL окружены запятыми, даже первой и последней. – mathguy

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