2016-06-24 1 views
-1

테이블에는 Title 필드와 Tags 필드가 있습니다. 태그는 문서로부터 잠재 Dirichlet 할당 (LDA)을 통해 생성되며, 예를 들어, '물고기, 오븐, 시간', 'BBQ, 맥주'또는 '고기, BBQ'. 태그의 길이는 고정되어 있지 않습니다.가능한 한 많은 쉼표로 구분 된 태그와 일치하는 TSQL

주어진 태그 집합이 주어지면 태그 순서와 상관없이 일치하는 최대 태그 수를 가진 레코드를 찾는 방법은 무엇입니까? 'BBQ가, 고기'가 주어진다면

그래서, 가장 좋은 결과는 '고기, BBQ'를해야한다. '바베큐, 생선, 크림'은 모두 3 개의 레코드가 모두 반환 될 수 있습니다 (모두 하나의 일치하는 태그가 있음).

+0

분할에게 단어를 사용하여 채울 필요 문서 – Paparazzi

+0

"한 물고기, 두 물고기, 붉은 물고기, 푸른 물고기"에서 "물고기"가 몇 번이나 일치합니까? 그것은 1 또는 5로 간주됩니까? _ (Four, Sir!) _ – HABO

답변

1

사용 this function 및이 하나

CREATE FUNCTION dbo.getCountOfMatch (@mainString VARCHAR(MAX), @searchString nvarchar(max)) 
    RETURNS 
     INT 
    AS 
    BEGIN 
     DECLARE @returnCount INT 

     SELECT 
      @returnCount = COUNT(1) 
     FROM 
      splitstring(@mainString) A INNER JOIN 
      splitstring(@searchString) B ON A.Name = B.Name 

     RETURN @returnCount 
    END 

업데이트

SELECT TOP 1 // What you want 
     Title, 
     Tags 
    FROM 
    (
     SELECT 
      A.Title, 
      A.Tags, 
      dbo.getCountOfMatch(A.Tags, @search) CountTags -- The number of matches. 
     FROM 
      TABLE A 
    ) B 
    ORDER BY B.CountTags DESC 

DECLARE @searchText NVARCHAR(MAX) = 'BBQ, meat' 
DECLARE @query NVARCHAR(MAX) = ' 
     SELECT 
      * 
     FROM 
      Table 
     WHERE ' 

SELECT 
    @query += 
    (
     SELECT 
      'Tags like ''%' + A.Name + '%'' AND ' -- Dont forget trim! 
     FROM 
      splitstring(@searchText) A 
     FOR XML PATH ('') 
    ) 

SELECT @query = LEFT(@query, LEN(@query) - 4) + 'ORDER BY LEN(Tags)' -- For exactly matching: LEN(Tags) = LEN(@searchText) 

EXEC sp_executesql @query 

질의 모양을 만들기;

SELECT 
     * 
    FROM 
     Table 
    WHERE 
     Tags like '%BBQ%' AND 
     Tags like '%meat%' 
    ORDER BY LEN(Tags) 
+0

작은 샘플에서도 (14K 행에서 17 초 걸립니다) 잘 작동하지만 강렬하게 느립니다. –

+0

답변이 업데이트되었습니다. 다시 시도해 볼 수 있습니까? – NEER

0

두 개의 UDF와 함께 검색의 조회 율 (%)을 리턴 할 수 있습니다. 예를

Select [dbo].[udf-Str-Match-Rate]('Dog,House,Custom',',','The dog house is red',' ') 

반환 0.6666 들어

- 3 개 단어의 2/문구가 발견되었다.

각각

는 별개의 단어 결과

나는 또한 (이것은 선택 사항입니다)

1 UDF 혼자 서서이 될 수있는 사운 덱스를 포함 팽창 방지하기 위해 테스트 자신의 구분 할 수 있습니다 독립적으로 사용됩니다.

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--  Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|') 

Returns @ReturnTable Table (Key_PS int IDENTITY(1,1) NOT NULL , Key_Value varchar(max)) 

As 

Begin 
    Declare @intPos int,@SubStr varchar(max) 
    Set @IntPos = CharIndex(@delimeter, @String) 
    Set @String = Replace(@String,@[email protected],@delimeter) 
    While @IntPos > 0 
     Begin 
     Set @SubStr = Substring(@String, 0, @IntPos) 
     Insert into @ReturnTable (Key_Value) values (@SubStr) 
     Set @String = Replace(@String, @SubStr + @delimeter, '') 
     Set @IntPos = CharIndex(@delimeter, @String) 
     End 
    Insert into @ReturnTable (Key_Value) values (@String) 
    Return 
End 

두 번째 UDF는 첫 번째

CREATE FUNCTION [dbo].[udf-Str-Match-Rate] (@SearchFor varchar(max),@SearchForDelim varchar(5),@SearchIn varchar(max),@SearchInDelim varchar(5)) 

-- Syntax : Select [dbo].[udf-Str-Match-Rate]('Dog,House,Custom',',','The dog house is red',' ') 

Returns money 
AS 
    BEGIN 

    Declare @RetVal money 

    ;with cteSearchFor as (Select Distinct Key_Value from [dbo].[udf-Str-Parse](@SearchFor ,@SearchForDelim)) 
     ,cteSearchIn as (Select Distinct Key_Value from [dbo].[udf-Str-Parse](@SearchIn,@SearchInDelim)) 
     ,cteWordCnt as (Select Words=cast(count(*) as money) From cteSearchFor) 
    Select @RetVal = isnull(Count(*)/max(Words),0) 
     From cteSearchFor S 
     Join cteWordCnt W on 1=1 
     Join cteSearchIn C 
     on S.Key_Value = C.Key_Value 
     or Soundex(S.Key_Value) = Soundex(C.Key_Value) 

    Return @RetVal 

    END 
+0

Soundex가 아마 너무 많은 히트 곡을 반환 할 것입니다. – Paparazzi

0

테이블 태그를 생성하고 다시 AA FK와 행마다 별도의 테이블 하나에 밖으로 stringsplit

tags 
title PK 
tag PK 

select title, count(*) 
from tags 
where tag in ('BBQ', 'fish', 'cream') 
group by title 
having count(*) > 1 

SELECT * 
from table 
join dbo.splitstring(table.tags) 
관련 문제