2016-11-01 73 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