2011-01-24 13 views
1

私は非常にトリッキーな問題を抱えています。mysqlデータベースで全文検索をする必要があります

それぞれの製品には、Brand and Modelといくつかの詳細が追加された、異なる倉庫の製品リストがあります。 Modelは同じ製品の異なる倉庫とはかなり異なる場合がありますが、Brandは常に同じです。

私が1つのテーブルに保管するすべての製品のリストは、Productテーブルと言いましょう。 次に、私は別のテーブルを持っています - Model正式モデル名Brand、画像、説明などの追加の詳細プラス私はすべてのキーワードを手動で追加しようとするキーワード列があります。

ここに問題があります。倉庫から受け取った各製品と、Modelテーブルの1つのレコードを関連付ける必要があります。今ではブールモードでフルテキスト検索を使用していますが、それはかなり苦痛で、うまく機能しません。私は多くの手作業をする必要があります。

  • WINT.SPORT3D
  • WINT.SPORT3D XL
  • WINT.SPORT 3D
  • WINT.SPORT3D MO
  • 冬のスポーツを:ここで

    は、私が持っている名前のほんの一例です3D

これらのすべての項目の正しい名前は次のとおりです。WINTER SPORT 3Dであるため、すべて同じモデルに割り当てる必要があります。

したがって、問題を解決するために全文検索やその他の手法を改善する方法はありますか?

私が使用しているデータベースはMySQLですが、変更しないことをお勧めします。

+0

は 'bmw' ... – ajreal

答えて

1

私は一緒にテーブルのより正式な定義置くことから始めましょう:私はあなたの「モデル」テーブルへの外部キーとして使用してlocal_idのだ。ここ

warehouse: 
    warehouse_id, 
    warehouse_product_id, 
    product_brand, 
    product_name, 
    local_id 

を - しかし、さらなる混乱を避けるために、

local: 
    id, 
    product_brand, 
    product_name 

「製品」と表記している表は冗長であるようです。

明らかに、データが相互参照されるまで、local_idはnullになります。それが移入された後、しかし、それは変更する必要はありません、とWAREHOUSE_ID、バンドや製品を考えると、簡単にあなたのローカル記述を見つけることができます。

SELECT local.* 
FROM local, warehouse 
WHERE local.id=warehouse.local_id 
AND warehouse.product_brand=local.product_brand 
AND warehouse_id=_____ 
AND warehouse.product_brand=____ 
AND warehouse.product_name=____ 

だから、あなたがする必要があるすべてはリンクを移入です。 Soundexはかなり粗雑なツールです。これに対しては、より良い解決策はLevenstein distance algorithmです。各行は(Wとして以前のクエリからの値を用いるものとして最良一致を識別するための

SELECT w.* 
FROM warehouse w 
WHERE w.local_id IS NULL; 

...:移入する必要が倉庫テーブルの行のセットを考えるmysql implementation here

があります。*)....

SELECT local.id 
FROM local 
WHERE local.product_brand=w.product_brand 
ORDER BY levenstein(local.product_name, w.product_name) ASC 
LIMIT 0,1 

しかし、2つの文字列が完全に異なる場合でも、これは最もよく一致します。したがって、...

SELECT local.id 
FROM local 
WHERE local.product_brand=w.product_brand 
AND levenstein(local.product_name, w.product_name)< 
    (IF LENGTH(local.product_name)<LENGTH(w.product_name), 
      LENGTH(local.product_name), LENGTH(w.product_name))/2 
ORDER BY levenstein(local.product_name, w.product_name) ASC 
LIMIT 0,1 

...一致する文字列の半分以上が必要です。

は、これは、単一の更新ステートメントで実装できます。

UPDATE warehouse w 
SET local_id=(
    SELECT local.id 
    FROM local 
    WHERE local.product_brand=w.product_brand 
    AND levenstein(local.product_name, w.product_name)< 
    (IF LENGTH(local.product_name)<LENGTH(w.product_name), 
      LENGTH(local.product_name), LENGTH(w.product_name))/2 
    ORDER BY levenstein(local.product_name, w.product_name) ASC 
    LIMIT 0,1 
) 
WHERE local_id IS NULL; 
+0

おかげで、symcbeanとして、製品名対ブランド' BMW'を区別するようなことはできません。あなたのメソッドを実装するのに時間がかかりましたが、今はもっとうまくいくようです。ありがとうございました :) – Dimitry

1

お試しSoundexあなたのすべての例はW532に解決され、最後の例はW536に解決されます。だから、あなたはできます

  1. SoundexValueという製品とモデルに列を追加し、各製品ののSoundex値を計算し、モデル
  2. は、モデル・テーブル内のものにPRODUCT表でのSoundex値を比較します。高いマッチング率を得るには、範囲(+/- 5)を使用する必要があります。
  3. 80/20ルールに従ってください。つまり、簡単に脱落しない20%の手作業の80%を費やします。
関連する問題