好的,使用SQL Server 2008.在我的网页上,我有一个文本框,其中连接了jQuery-UI AutoComplete。
现在我需要一个存储过程来搜索单个表的所有列(或者我想的多个连接表),以查找来自文本框/自动完成AJAX调用的搜索字符串,并返回“建议的”搜索字符串。我正在使用AdventureWorks数据库进行测试(产品表)
因此,例如,产品表中包含产品名称和产品编号(以及其他)的列,我想根据用户输入返回建议的搜索字符串,他们可以输入产品名称和/或产品编号。
我让它在单个列中工作很简单。有什么想法吗?
答案 0 :(得分:6)
我将建议全文搜索(MS'或Lucene将起作用)下面的代码使用MSSQL FTS作为我目前在我的应用程序中使用的内容。
如果您还没有安装FTS搜索。如果您已检查该服务是否正在运行。 在管理工作室运行此操作以设置目录并添加产品表;和目录中的颜色/名称/产品编号。
USE [AdventureWorks]
GO
CREATE FULLTEXT CATALOG [ProductsTest]WITH ACCENT_SENSITIVITY = OFF
AUTHORIZATION [dbo]
GO
USE [AdventureWorks]
GO
CREATE FULLTEXT INDEX ON [Production].[Product] KEY INDEX [PK_Product_ProductID] ON ([ProductsTest]) WITH (CHANGE_TRACKING AUTO)
GO
USE [AdventureWorks]
GO
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([Color])
GO
USE [AdventureWorks]
GO
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([Name])
GO
USE [AdventureWorks]
GO
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([ProductNumber])
GO
USE [AdventureWorks]
GO
ALTER FULLTEXT INDEX ON [Production].[Product] ENABLE
GO
然后,您可以立即对所有列运行查询;例如银(选择颜色和名称)
Select * from production.product where
contains(*, '"Silver*"')
查询上的*将找到Silver *,因此您可以使用此功能在用户输入时构建结果。要考虑的一件事是谷歌让这项工作实时 - 如果您正在搜索大量数据能够在不中断用户输入的情况下获取数据。我认为一般人们通过从他们正在寻找的第一个字母输入来使用这些搜索 - 我接受会有拼写错误 - 你可以在他们按下的每个空格之后实施一个拼写检查器来处理它。或者存储运行的搜索并查看拼写错误并更改代码以根据映射处理(或使用自定义同义词库在FTS中)。
排名对任何企业来说都是一个有趣的发展问题;你是否找到Mountain Frame的第一个结果 - 或者你想按销售额或价格来衡量它们吗?如果用户键入多个文本术语,您可以使用FTS根据搜索字符串生成排名。
select aa.rank, bb.*
From containstable(production.product, *, '"Mountain" and "Silver*"') aa
inner join production.product bb
on aa.[key] = bb.productid
order by rank desc
这会返回30行;和权重基于用户输入的文本来确定第一位记录。在任何一种情况下,您可能都希望添加编码排名以调整结果以满足您的业务需求 - 排名最高价格的小部件1可能不是这样。这就是为什么你要存储人们搜索/点击的内容,以便你可以在以后分析结果。
.Net有一个非常好的language parser,用于翻译输入到FTS可用语言的Google格式字符串查询,可以让您熟悉使用您网站的任何布尔搜索。
您可能还希望通过审核用户输入的内容并最终访问并使用成功地图来更改最终建议以实际使其与用户相关,从而添加一些智慧人群功能。
作为最终建议,如果这是一个商业网站,你可能想看看Easyask这是一个可怕的自然语言处理器
答案 1 :(得分:3)
使用soundex函数是匹配多列中类似“项”的最简单方法。但Levenshtein Edit Distance更好的匹配算法实现速度快得多。这是函数中包含的T-SQL implementation。使用它来匹配类似的搜索字词。
编辑 Levenshtien的实例(基于gbn的SQL)
假设你命名了你的Levenshtein T-SQL函数lvn(为了简洁起见)那么你可以这样做:
SELECT productname FROM foo WHERE productname
LIKE '%myinput%' OR lvn(myinput) < 3
UNION
SELECT productnumber FROM foo WHERE productnumber
LIKE '%myinput%' OR lvn(myinput) < 3
UNION
...
ORDER BY 1 -- one-based column index sort for UNION queries
是的。那么简单。顺便说一下,我将T-SQL levenshtein链接更新为更有意义的内容,这是一个公认的SO答案。
答案 2 :(得分:2)
编辑:使用UNION加入单独的查询
SELECT productname FROM foo WHERE productname LIKE '%myinput%'
UNION
SELECT productnumber FROM foo WHERE productnumber LIKE '%myinput%'
UNION
...
除非使用动态SQL
,否则没有自动扫描所有列的方法答案 3 :(得分:0)
我创建了一个示例SQL,它将返回谷歌样式搜索结果。 你可以尝试这个T-SQL。您还可以添加多个表列搜索条件。
ALTER PROC [dbo].[USP_GetDoctorLookupList]
(
@SearchText varchar(50),
@ItemCount int
)
AS
BEGIN
SET @SearchText = RTRIM(@SearchText) + '%'
BEGIN
SELECT TOP (@ItemCount) *
FROM
(
SELECT
CASE
WHEN RTRIM(LTRIM(d.cdocname)) LIKE @SearchText then 1
WHEN RTRIM(LTRIM(d.cdeano)) LIKE @SearchText then 2
END OrderBy,
d.docid_PK,
d.cdocname,
d.cdeano
FROM doctor d
WHERE
(d.cdocname LIKE @SearchText
OR d.cdeano LIKE @SearchText
)
) Doc ORDER BY OrderBy, cdocname
END
END