복붙노트

[SQL] 어떻게 비슷한 결과 및 종류의 유사성을 찾는 방법은?

SQL

어떻게 비슷한 결과 및 종류의 유사성을 찾는 방법은?

어떻게 유사성에 의해 주문 레코드를 쿼리합니까?

예. "주식 오버플로"검색하면 반환

예. "LO"에 대한 검색 반환합니다 :

해결법

  1. ==============================

    1.난 당신이 다른 전체 문자열에 대해 전체 문자열을 검색 할 때 Levenshtein 거리가 잘 될 수 있다는 것을 발견했다,하지만 당신은 문자열 내에서 키워드를 찾을 때,이 방법은 (때때로) 원하는 결과를 반환하지 않습니다. 또한, SOUNDEX 함수는 영어 이외의 언어에 적합하지 않습니다, 그래서 그것은 매우 제한됩니다. 당신은 LIKE 멀리 얻을 수 있지만, 기본적인 검색을 위해 정말. 당신은 당신이 달성하고자하는 것에 대해 다른 검색 방법을 조사 할 수 있습니다. 예를 들면 :

    난 당신이 다른 전체 문자열에 대해 전체 문자열을 검색 할 때 Levenshtein 거리가 잘 될 수 있다는 것을 발견했다,하지만 당신은 문자열 내에서 키워드를 찾을 때,이 방법은 (때때로) 원하는 결과를 반환하지 않습니다. 또한, SOUNDEX 함수는 영어 이외의 언어에 적합하지 않습니다, 그래서 그것은 매우 제한됩니다. 당신은 LIKE 멀리 얻을 수 있지만, 기본적인 검색을 위해 정말. 당신은 당신이 달성하고자하는 것에 대해 다른 검색 방법을 조사 할 수 있습니다. 예를 들면 :

    당신은 당신의 프로젝트에 대한 검색 기준으로 루씬을 사용할 수 있습니다. 그것은 대부분의 주요 프로그래밍 언어로 구현 그리고 그것은 매우 빠르고 다양한 것입니다. 이 방법은뿐만 아니라 하위 문자열 검색으로, 아마 최고입니다, 또한 편지 전위, 접두사와 접미사 (모두 함께). 그러나 (가끔 작동하지만에 독립적 인 스크립트를 업데이트 할 CRON을 사용하여) 별도의 인덱스를 유지해야합니다.

    당신은 MySQL의 솔루션을 원하는 경우 또는, 전체 텍스트 기능을 빠르게 저장 프로 시저에 비해 꽤 좋은, 그리고 확실히. 테이블이의 MyISAM하지 않은 경우, 당신은 당신의 전체 텍스트 검색을 수행, 임시 테이블을 만들 수 있습니다 :

    CREATE TABLE IF NOT EXISTS `tests`.`data_table` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `title` varchar(2000) CHARACTER SET latin1 NOT NULL,
      `description` text CHARACTER SET latin1 NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
    

    당신이 그것을 직접 만드는 귀찮게하지 않으려면 어떤 임의의 데이터를 생성하는 데이터 생성기를 사용하여 ...

    ** 참고 ** : 컬럼 형식 대신 라틴와 사례를 구분의 대소 문자를 구분 검색을 수행 할 latin1_bin해야한다. 유니 코드 문자열, 나는 대소 문자 구분 검색을 위해 utf8_general_ci을 대소 문자 구분을 위해 utf8_bin 추천합니다.

    DROP TABLE IF EXISTS `tests`.`data_table_temp`;
    CREATE TEMPORARY TABLE `tests`.`data_table_temp`
       SELECT * FROM `tests`.`data_table`;
    
    ALTER TABLE `tests`.`data_table_temp`  ENGINE = MYISAM;
    
    ALTER TABLE `tests`.`data_table_temp` ADD FULLTEXT `FTK_title_description` (
      `title` ,
      `description`
    );
    
    SELECT *,
           MATCH (`title`,`description`)
           AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE) as `score`
      FROM `tests`.`data_table_temp`
     WHERE MATCH (`title`,`description`)
           AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE)
     ORDER BY `score` DESC;
    
    DROP TABLE `tests`.`data_table_temp`;
    

    MySQL의 API 레퍼런스 페이지에서 더 많은 그것에 대해 읽기

    이것의 단점은 단어 "와 같은 비슷한 소리"편지 전위 또는 찾지 것입니다.

    ** UPDATE **

    검색에 루씬을 사용하여, 당신은 단순히이 작업은 단순히 "; PHP searchindexer.php CD / 경로 /로 / 스크립트"에 ig (PHP 스크립트를 실행하는 cron 작업 (모든 웹 호스트는이 "기능"이)를 만들어야합니다 ) 그 인덱스를 업데이트합니다. "문서"(행, 데이터 등)의 인덱싱 수천 몇 초, 심지어 분 정도 걸릴 수 있습니다, 그러나 이것은 모든 검색이 가능한 한 빨리으로 수행되는 것을 보장하는 것입니다되는 이유. 따라서 서버에서 실행되도록 지연 작업을 생성 할 수 있습니다. 그것은 하룻밤 할 수있다, 또는 다음 시간에, 이것은 당신에게 달려 있습니다. PHP 스크립트는 다음과 같이 보일 것입니다 :

    $indexer = Zend_Search_Lucene::create('/path/to/lucene/data');
    
    Zend_Search_Lucene_Analysis_Analyzer::setDefault(
      // change this option for your need
      new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
    );
    
    $rowSet = getDataRowSet();  // perform your SQL query to fetch whatever you need to index
    foreach ($rowSet as $row) {
       $doc = new Zend_Search_Lucene_Document();
       $doc->addField(Zend_Search_Lucene_Field::text('field1', $row->field1, 'utf-8'))
           ->addField(Zend_Search_Lucene_Field::text('field2', $row->field2, 'utf-8'))
           ->addField(Zend_Search_Lucene_Field::unIndexed('someValue', $someVariable))
           ->addField(Zend_Search_Lucene_Field::unIndexed('someObj', serialize($obj), 'utf-8'))
      ;
      $indexer->addDocument($doc);
    }
    
    // ... you can get as many $rowSet as you want and create as many documents
    // as you wish... each document doesn't necessarily need the same fields...
    // Lucene is pretty flexible on this
    
    $indexer->optimize();  // do this every time you add more data to you indexer...
    $indexer->commit();    // finalize the process
    

    그런 다음이 있습니다 (기본 검색) 검색 방법 기본적으로 :

    $index = Zend_Search_Lucene::open('/path/to/lucene/data');
    
    // same search options
    Zend_Search_Lucene_Analysis_Analyzer::setDefault(
       new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
    );
    
    Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');
    
    $query = 'php +field1:foo';  // search for the word 'php' in any field,
                                     // +search for 'foo' in field 'field1'
    
    $hits = $index->find($query);
    
    $numHits = count($hits);
    foreach ($hits as $hit) {
       $score = $hit->score;  // the hit weight
       $field1 = $hit->field1;
       // etc.
    }
    

    여기에 자바, PHP 및 닷넷 Lucene에 대한 좋은 사이트입니다.

    결론적으로 각 검색 방법은 자신의 장점과 단점을 가지고 :

    내가 잊어 버린 경우 / 놓친 아무것도 의견을 주시기 바랍니다.

  2. ==============================

    2.1. 유사성

    1. 유사성

    Levenshtein를 들어 MySQL의 I에 www.codejanitor.com/wp/2007/02/10/levenshtein-distance-as-a-mysql-stored-function에서 이걸 발견

    SELECT 
        column, 
        LEVENSHTEIN(column, 'search_string') AS distance 
    FROM table 
    WHERE 
        LEVENSHTEIN(column, 'search_string') < distance_limit
    ORDER BY distance DESC
    

    2. 포함하는, 사례를 구분

    기본적으로 케이스를 구분하지 않습니다 MySQL은,의 LIKE 문을 사용합니다. 이 % 와일드 카드, 그래서 전 SEARCH_STRING 후 모든 문자열이있을 수 있습니다.

    SELECT 
        *
    FROM 
        table
    WHERE 
        column_name LIKE "%search_string%"
    

    3. 함유, 대소 문자를 구분

    MySQL의 매뉴얼 도움 :

    내 MySQL의 설정이 latin1_general_cs를 지원하지 않거나 latin1_bin, 그러나 저 이진 UTF8로 정렬 utf8_bin를 사용하는 것이 좋은 일했다 소문자를 구분합니다 :

    SELECT 
        *
    FROM 
        table
    WHERE 
        column_name LIKE "%search_string%" COLLATE utf8_bin
    

    / 3. 2. Levenshtein 거리 기준으로 정렬

    SELECT 
        column, 
        LEVENSHTEIN(column, 'search_string') AS distance // for sorting
    FROM table 
    WHERE 
        column_name LIKE "%search_string%"
        COLLATE utf8_bin // for case sensitivity, just leave out for CI
    ORDER BY
        distance
        DESC
    
  3. ==============================

    3.이 유사성의 당신의 정의는 의미 론적 유사성 것 같다. 그래서 이러한 유사성 기능을 구축하기 위해, 당신은 의미 론적 유사성 조치를 사용해야합니다. 이 작업에 들어가기 전에 범위를 결정하는 것이 좋습니다 그래서 문제에 대한 작업의 범위는 년에 몇 시간에서 다를 수 있습니다. 내가 파악하지 않은 어떤 데이터는 유사성 관계를 구축하기 위해 않아도됩니다. 나는 액세스에게 문서의 데이터 집합 쿼리의 데이터 집합을 가정합니다. 사용자는 단어 (예를 들어, 조건부 확률)의 동시 발생을 시작할 수있다. 당신은 그들이 매우 인기가 있기 때문에 단순히 단어의 대부분을 관련 당신이 정지 단어의 목록을 얻을 것을 빨리 발견 할 것입니다. 조건부 확률의 리프트를 사용하여 중지 단어를 돌봐하지만 적은 수의 오류에 관계가 발생하기 쉬운 (당신의 대부분의 경우)를 만들 것입니다. 당신은 Jacard을 시도 할 수 있지만 대칭이기 때문에 그것을 발견 할 수는 없을 것이다 많은 관계가있을 것입니다. 그럼 당신은 기본 단어에서 짧은 거리에서만 나타 관계를 고려해 볼 수 있습니다. 당신은 (그리고해야한다) 일반 코퍼스의 (예를 들어, 위키 백과)에 관계 기반과 사용자 특정 (예를 들어, 자신의 이메일)을 고려할 수 있습니다.

    이 유사성의 당신의 정의는 의미 론적 유사성 것 같다. 그래서 이러한 유사성 기능을 구축하기 위해, 당신은 의미 론적 유사성 조치를 사용해야합니다. 이 작업에 들어가기 전에 범위를 결정하는 것이 좋습니다 그래서 문제에 대한 작업의 범위는 년에 몇 시간에서 다를 수 있습니다. 내가 파악하지 않은 어떤 데이터는 유사성 관계를 구축하기 위해 않아도됩니다. 나는 액세스에게 문서의 데이터 집합 쿼리의 데이터 집합을 가정합니다. 사용자는 단어 (예를 들어, 조건부 확률)의 동시 발생을 시작할 수있다. 당신은 그들이 매우 인기가 있기 때문에 단순히 단어의 대부분을 관련 당신이 정지 단어의 목록을 얻을 것을 빨리 발견 할 것입니다. 조건부 확률의 리프트를 사용하여 중지 단어를 돌봐하지만 적은 수의 오류에 관계가 발생하기 쉬운 (당신의 대부분의 경우)를 만들 것입니다. 당신은 Jacard을 시도 할 수 있지만 대칭이기 때문에 그것을 발견 할 수는 없을 것이다 많은 관계가있을 것입니다. 그럼 당신은 기본 단어에서 짧은 거리에서만 나타 관계를 고려해 볼 수 있습니다. 당신은 (그리고해야한다) 일반 코퍼스의 (예를 들어, 위키 백과)에 관계 기반과 사용자 특정 (예를 들어, 자신의 이메일)을 고려할 수 있습니다.

    모든 조치가 좋다하고 다른 사람을 통해 몇 가지 이점이있을 때 매우 곧 당신은 유사성 대책을 충분히해야합니다.

    조치를 결합하기 위해, 나는 분류 문제로이 문제를 줄일 것을 좋아합니다.

    당신은 "관련"그들을 단어의 파리의 데이터 세트를 구축하고 레이블을해야한다. 당신이 할 수있는 큰 표시된 데이터 집합을 구축하기 위해 :

    그런 다음 쌍 기능으로이 모든 조치를 사용합니다. 지금 당신은 감독 분류 문제의 도메인에 있습니다. 사용자의 필요에 따라 평가, 데이터 세트에 대한 분류를 구축하고 사용자의 요구에 맞는 유사성 측정을 얻을.

  4. from https://stackoverflow.com/questions/3338889/how-to-find-similar-results-and-sort-by-similarity by cc-by-sa and MIT license