0

これが私が抱えている問題です。データベース内のテーブルから類似した行を返したいです。次のテキストを含む 2 行を考えてみましょう。

'Cisco phones cannot dial out'
'Phones are not working for outgoing calls'

これらは2つの異なる行です...私はこのようなことをしようとしました:

DECLARE @TheTest varchar(1000)
DECLARE @TheResult varchar(1000)

SET @TheTest = ('Cisco phones cannot dial out')
SET @TheResult = ('Phones are not working for outgoing calls')

CREATE TABLE #Test
(
MyCol varchar(1000)
)

INSERT INTO #Test(MyCol)
SELECT @TheResult

SELECT * FROM #Test WHERE LOWER(MyCol) LIKE '%' + LOWER(@TheTest) + '%'

DROP TABLE #Test

しかし、結果は 0 行が返されました。文字列 TheTest が文字列 @TheResult に十分に近くないため、よくわかります...しかし、phones という単語が両方のテキストに表示されるため、実際にこの行を返すソリューションが必要です。

このようなもののために、単語を分離し、一般的な単語を取り除くために、もっと精巧なものを構築する必要がありますか? 特定の Web サイトで見られる機能を模倣したい:

ここに画像の説明を入力

4

3 に答える 3

2

あなたの質問について私が理解していることから、SQL FullTextでさえあなたが望むものを手に入れることはできません。
Lucene タイプの機能を探しています。
彼らは、同様の質問を見つけるために SO で Lucene を使用していると思います。

簡単な方法は、単語を解析してから語幹 (Porter) を取得し、テーブルに入力することです。
ワード ブレークで Regex を使用するだけで開始できます。
または、ステミングをスキップすることもできますが、多くの一致 (一致など) が失われます。
一意の単語/語幹のみをインデックスに登録します。
単語が 1 つのフレーズで 4 回表示され、別のフレーズで 2 回表示される場合、スコア付けに問題があります。
そして、単語ごとに 1 つの一致がより意味のあるスコアだと思います。
次に結合を行い、結合された単語の数を数えます。
12 語での 12 一致は、20 語での 14 一致よりも優れているため、正規化する必要があります。
Like 2 * は / (単語数 A + 単語数 B) に一致します。

もう 1 つの方向は、ステムではなく、レーベンスタイン距離のようなファジー マッチを使用することです。

あなたのサンプルでは、​​電話のみが一致するため、スコアが低くなります。
しかし、Lucene や Google でさえ、これに高いスコアを付けるのは難しいでしょう。
単語は異なるが意味は同じである 2 つのフレーズの英語を分解することは、非常に複雑です。

于 2012-10-24T14:35:49.170 に答える
0

SOUNDEX2 つの文字列の類似性を返すことをお勧めします: http://msdn.microsoft.com/en-us/library/ms187384.aspx

2 つの文字列間の類似性を保持する varchar を返します。次に、varchar が、定義した許容可能な「類似範囲」内にあるかどうかを評価できます。

于 2012-10-24T14:11:06.843 に答える
0

1つの方法は、関数を使用することSplitです(ここにデモがあります):

CREATE FUNCTION [dbo].[Split]
(
    @ItemList NVARCHAR(MAX), 
    @delimiter CHAR(1)
)
RETURNS @IDTable TABLE (Item VARCHAR(50))  
AS      

BEGIN    
    DECLARE @tempItemList NVARCHAR(MAX)
    SET @tempItemList = @ItemList

    DECLARE @i INT    
    DECLARE @Item NVARCHAR(4000)

    SET @i = CHARINDEX(@delimiter, @tempItemList)

    WHILE (LEN(@tempItemList) > 0)
    BEGIN
        IF @i = 0
            SET @Item = @tempItemList
        ELSE
            SET @Item = LEFT(@tempItemList, @i - 1)
        INSERT INTO @IDTable(Item) VALUES(@Item)
        IF @i = 0
            SET @tempItemList = ''
        ELSE
            SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i)
        SET @i = CHARINDEX(@delimiter, @tempItemList)
    END 
    RETURN
END  

これで、いずれかの単語が列に含まれているかどうかを確認できます。

DECLARE @TheTest varchar(1000)
DECLARE @TheResult varchar(1000)

SET @TheTest = ('Cisco phones cannot dial out')
SET @TheResult = ('Phones are not working for outgoing calls')

CREATE TABLE #Test
(
MyCol varchar(1000)
)

INSERT INTO #Test(MyCol)
    SELECT @TheResult

Declare  @searchWords Table(Item varchar(100));
INSERT INTO @searchWords
    SELECT Item FROM dbo.Split(@TheTest, ' ');

SELECT * FROM #Test t
WHERE EXISTS
(
    SELECT 1 
    FROM dbo.Split(t.MyCol, ' ')cw INNER JOIN @searchWords sw
        ON cw.Item = sw.Item
);

DROP TABLE #Test 
于 2012-10-24T14:22:26.153 に答える