1

我有两张桌子:

Vehicles 
make    model         modification    
Audi     A 5         A 5 2010 Sportsback 2.8      
Audi     A 5         A 5 2012 Quattro L     
Audi     A 5         A 5 Cabriolet 

matchingModel 
make    model      modContain    modEnd    finalModel    
Audi     A 5       Sportback              A5 Sportback
Audi     A 5                       L        A5 L
Audi     A 5                                A5

我的任务是通过查找匹配项来获得最合适的 finalModel(可以在下面的选择中看到)。首先我尝试加入表格

(SELECT 
matchingModel.finalModel
  FROM vehicles
    LEFT OUTER JOIN matchingModel ON 
matchingModel.TEXT1 = vehicles.make

    AND vehicles.model = nvl(matchingModel.model,vehicles.model)
    AND vehicles.modification LIKE decode(matchingModel.modContain, NULL, vehicles.modification, '%'||matchingModel.modContain||'%')
    AND vehicles.modification LIKE decode(matchingModel.modEnd, NULL, vehicles.modification, '%'||' '||matchingModel.modEnd)
)
AS bestMatch

但这不起作用,因为 Sportsback 被发现为 sportsback,后来它被覆盖为简单的 A5,因为它也匹配。

所以接下来我通过“nvling”所有可能的选项来实现这一点:nvl(nvl(nvl(选择制造,模型适合和modContains在修改中间并且选项单元格为空),(选择制造,模型适合和modEnd 就像 Modification 的结尾,并且 modEnd 不为空),(选择适合的品牌和模型等等)) AS Bestmatch 这有效,但速度很慢(并且两个表都有超过 500k 的记录)。

这只是非常庞大的选择的一部分,因此很难以这种正常方式重写。无论如何,问题是,是否有任何最佳实践如何在 oracle 中快速获得最佳匹配?我遇到的问题是性能,或者值适合两次,或者“where”子句不起作用,因为我不知道 modContain 或 modEnd 是否为空。

先感谢您。对不起英语。

4

2 回答 2

1

它还没有完成,但我制定了一个示例,您可以继续为自己制定:SQL Fiddle Demo

select * from (
(select 
  case when v.modification like '%'||m.modContain||'%' then 2
       when m.modcontain is null                       then 1
                                                       else 0 end m1,
       case when v.modification like '%'||m.modend     then 2
            when m.modend is null                      then 1
                                                       else 0 end m2
 , m.make mmake, m.model mmodel, modcontain, modend, finalmodel
 , v.make vmake, v.model vmodel, modification
from vehicles v, matchingmodel m
where
     v.make  = m.make
 and soundex(v.model) = soundex(m.model) ) ) x
order by m1+m2 desc

因此,子查询将匹配项加在一起,最高匹配项应该是您的最佳匹配项。我还使用了 soundex,它也可能对您有所帮助,因为它们Sportback并不Sportsback完全相同,这有助于我制作A5A 5制作相同的东西。此外,为了加快速度,您将不得不大量分配良好的指标并查看解释计划,特别是如果您有 50 万条记录。这不是一件容易的事。

对于编写未经测试的程序(这是一个好主意)的想法,它可能看起来像这样:

create or replace function vehicle_matching(i_vehicles vehicles%rowtype,
                                            i_matchingmodel matchingmodel%rowtype)
return number
is
   l_return number;
begin
   if   i_vehicles.modification like '%'||i_matchingmodel.modContain||'%' then 
      l_return := 3;
   elsif soundex(i_vehicles.modification) like '%'||soundex(i_matchingmodel.modContain)||'%' then
      l_return := 2;
...

   if i_vehicles.modification like '%'||i_matchingmodel.modend then
      l_return := l_return + 1; -- there is no i++ in PL/SQL
   elsif 
...

   return l_return;
end vehicle_matching;

此外,我还在想,使用它是否比使用它更有效INSTR,但我实际上并不认为是这种情况。 SUBSTR%

于 2012-10-02T21:11:44.703 回答
0

你可以考虑这样的事情:

编写一个查询以在任何部分匹配上返回 1,然后编写另一个查询以在另一个部分匹配上返回另一个 1 - 等等。

对所有可能计入“相似性”的列重复此操作

最后,您将找到 1 的总和(或计数)最高的行,这将是最接近的匹配。

于 2012-10-02T13:33:20.443 回答