2011-01-24 3 views
1

아주 까다로운 문제가 하나 있습니다.mysql 데이터베이스에서 전체 텍스트 검색이 필요합니다.

각 창고의 제품 목록은 Brand and Model이며 몇 가지 추가 정보가 있습니다. Model은 동일한 제품의 다른 창고와 매우 다를 수 있지만 Brand은 항상 같습니다.

모든 제품 목록 나는 하나의 테이블에 저장하는데, 그것이 Product 테이블이라고 가정 해 봅시다. 그럼 다른 표가 있습니다 - Model, 올바른 모델명, Brand 및 추가 정보 (예 : 이미지, 설명 등) 플러스 나는 모든 키워드를 수동으로 추가하려고합니다.

여기에 문제가 있습니다. 창고에서받은 ​​각 제품을 내 Model 테이블의 하나의 레코드와 연결해야합니다. 지금은 부울 모드에서 전체 텍스트 검색을 사용하고 있지만 상당히 고통스럽고 잘 작동하지 않습니다. 나는 많은 수작업을해야한다.

  • WINT.SPORT3D
  • WINT.SPORT3D XL
  • WINT.SPORT 3D
  • WINT.SPORT3D MO
  • 겨울 스포츠를 : 여기에

    내가 가진 이름의 단지 몇 가지 예입니다 3D

이 모든 항목의 올바른 이름은 다음과 같습니다. WINTER SPORT 3D이므로 모두 동일한 모델에 지정해야합니다.

그래서 전체 텍스트 검색이나 다른 문제를 해결할 수있는 방법이 있습니까?

사용하는 데이터베이스가 MySQL이므로 변경하지 않는 것이 좋습니다.

+0

은'bmw' ... – ajreal

답변

1
내가 함께 테이블 형식적인 정의를 넣어 시작합니다

: 여기

warehouse: 
    warehouse_id, 
    warehouse_product_id, 
    product_brand, 
    product_name, 
    local_id 

나는 당신의 '모델'테이블에 외래 키로 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입니다. 거기에 채워진 될 필요가 창고 테이블에서 행 집합을 감안할 때 mysql implementation here

: (이전 쿼리에서 값을 사용으로 최적의 일치를 확인

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

를 ... 각 행에 대해 w로 . *) ....

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 문으로 구현 될 수있다 :

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

시도 . 모든 예제는 W532로 해결되지만 마지막 예제는 W536으로 해결됩니다. 그래서, 당신은 할 수 :

  1. 는 SoundexValue라는 제품 및 모델에 열을 추가하고
  2. 이 모델 표 것들에 제품 테이블의 Soundex와 값을 비교하여 각 제품 및 모델에 대한 Soundex와 값을 계산합니다. 보다 높은 일치율을 얻으려면 범위 (+/- 5)를 사용해야 할 수도 있습니다.
  3. 80/20 규칙을 따르십시오. 즉, 쉽게 빠지지 않는 20 %에 대해 수동 작업의 80 %를 보냅니다.
관련 문제