2016-11-01 44 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 OR 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

您打算如何提供“用户输入”(需要匹配的技能以及“OR”与“AND”等的选择?)当AND和OR类似时应该有什么选择可用你输入三个技能来搜索,或四个技能?只是技能的数量? – mathguy

+0

我们有一个预定义的技能列表,并将其显示在多选列表中。用户还可以选中一个框来使所有必要的技能(AND),或不选中(OR)。 – WOPR

+0

哦 - 所以你会寻找所有的技能,或任何一种技能 - 而不是其他组合。然后,在我提供的解决方案(适用于OR选择,任何一项技能匹配)中,您可以通过在外部选择中添加WHERE子句来获得AND版本(匹配的所有技能) - 只选择匹配数量等于技能的总数。 – 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'。另外,要在AND情景中使用它,只需使用'WHERE matches = 2'进行过滤。 –

+0

@HepC - 在一个更强大的设置中(尽可能强健,当基础数据甚至不是第一个正常形式时),输入(搜索技能)将在助手表中给出,解决方案将做一个连接而不是手动计数......但那是另一回事。 – mathguy

+0

@HepC - 常规字符串函数(LIKE,INSTR等)应尽可能优先于正则表达式 - 它们更快。此外,还有regexp_like,不需要regexp_instr,并且匹配模式可以更简单 - 在OP的设置中,所有令牌都被逗号包围,即使是第一个也是最后一个。 – mathguy