1

私は2つのテーブルを持っています:

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」することでこれを実現しました: modEnd は Modification の終了に似ており、modEnd は空ではありません), (make とモデルが適合する場所を選択するなど)) AS Bestmatch これは機能しますが、非常に低速です (両方のテーブルに 500k を超えるレコードがあります)。

これは非常に巨大な select の一部にすぎないため、この通常の方法で書き直すのは困難です。とにかく、問題は、Oracleでベストマッチを1回だけ高速で取得するベストプラクティスはありますか? modContain または modEnd が空かどうかわからないため、私が遭遇した問題は、パフォーマンス、または値が 2 回適合するか、「where」句が機能しないことです。

前もって感謝します。英語で申し訳ありません。

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

したがって、サブクエリは一致を合計し、最高の一致が最良の一致になるはずです。また、 とはまったく同じではないためSportback、あなたを助けるかもしれない soundex も使用しました。また、特に 50 万件のレコードがある場合は、高速化するために、適切なインデックスを割り当てて説明計画を監視することで多くの作業を行う必要があります。これは簡単なことではありません。SportsbackA5A 5

テストされていない手順 (これは良いアイデアです) を書くことについてのアイデアは、次のようになります。

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;

また、 を使用するよりもINSTRandを使用する方が効率的かどうかも考えていましたが、実際にはそうではないと思います。 SUBSTR%

于 2012-10-02T21:11:44.703 に答える
0

次のように考えることができます。

部分一致で 1 を返すクエリを作成し、別の部分一致で別の 1 を返す別のクエリを作成します。

「類似度」にカウントされるすべての可能な列に対してこれを繰り返します

最終的に、1 の合計 (またはカウント) が最大の行が見つかり、それが最も近い一致になります。

于 2012-10-02T13:33:20.443 に答える