SQL查询将整个句子与关键字匹配

时间:2017-12-14 23:10:10

标签: sql sql-server full-text-search

我正在尝试在网站上实现faq部分,之后会问一个问题,整个句子将再次匹配关键字列表,如果找到任何匹配,这将返回给用户。

数据库在MS SQL 2014上运行,

+----+----------------------------------+----------------------------------------------------------+
| ID | Keywords                         | Answer                                                   |
+----+----------------------------------+----------------------------------------------------------+
| 1  | opening, open, hour, hours, time | We are open from 9AM to 6PM every day, Monday to Sunday. |
+----+----------------------------------+----------------------------------------------------------+

在这种情况下,让我们假设用户会问以下问题:

  

你几点开门?

这将与关键字匹配,因为' time'如果使用的是关键字,则会返回第一个答案。

如果可能的话,我宁愿避免对句子中的每个单词使用。

我尝试使用contains,但这并不适用于整个句子:

SELECT * FROM FAQ
WHERE CONTAINS(Keywords,'"What time are you open?"');

http://sqlfiddle.com/#!6/895e5/1

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

我建议您对表格进行规范化并尝试使用

- 创建临时表并填充数据

Declare @keywordTable as TAble (ID INT, Keyword varchar(100))
declare @AnswerTable as table (ID int, Answer nvarchar(max))

declare @question nvarchar(max) = 'What time are you open?'
SET @question = REPLACE(@question,'?','')

    INSERT @keywordTable
    values 
    (1,'opening'),
    (1,'open'),
    (1,'hours'),
    (1,'hour'),
    (1,'time'),
    (2,'keyword2'),
    (2,'second')

insert @AnswerTable
values (1, 'We are open from 9AM to 6PM every day, Monday to Sunday.'),
(2, 'second question')

显示数据表

SELECT * FROM @keywordTable
  

ID关键字
1开1次打开1小时
1小时
  1次
2关键字2
2秒

SELECT * FROM @AnswerTable
  

ID答案
1我们每天上午9点到下午6点开放,周一至周五   星期天。
2秒问题

使用函数按字词分割问题

ALTER FUNCTION [MDM].[fn_SplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END

这是拆分功能的结果

SELECT * FROM [MDM].[fn_SplitString](@question,' ')
  

splitdata
什么时间
是你打开

最终查询

SELECT Answer from @AnswerTable where ID in (select ID FROM @keywordTable where keyword in (SELECT * FROM [MDM].[fn_SplitString](@question,' ')))

最终结果

  

答案
我们每天上午9点至下午6点开放,周一至周日。

答案 1 :(得分:0)

一种方法是将逗号分隔的关键字分解为不同的行,并将它们与句子匹配。

您可以使用任何标准分割器。在此处查看 this link 。我使用的是基于XML的,因为很可能您的输入不应包含任何有效字符。

我还为SQL添加了多个匹配项。这样,如果多个答案具有相同的关键字,则代码将选择具有最多关键字的答案。

See working demo

declare @question varchar(max)
set @question='What time are you open?'

create table t ( ID int,Keywords varchar(max), Answer varchar(max));

insert into t 
values
( 1,'opening, open, hour, hours, time','We are open from 9AM to 6PM every day, Monday to Sunday.'),
(2,'open,weekends', 'No we don''t!')

SELECT TOP 1 
Max(Answer) as Answer
FROM t outer apply (
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(Keywords, ',', '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   )T1

WHERE @question like '%'+Item+'%'
group by Id
order by count(1) desc