如何让一个sql搜索查询更强大?
Posted
技术标签:
【中文标题】如何让一个sql搜索查询更强大?【英文标题】:How to make a sql search query more powerful? 【发布时间】:2010-10-15 08:46:38 【问题描述】:我写了这个 sql 查询来在一个表中搜索:
SELECT * FROM TableName WHERE Name LIKE '%spa%'
表格包含这些行,例如:
-
太空公司。
温泉度假村。
温泉酒店。
备件。
WithoutTheKeyword。
我想知道如何编辑这个查询,让它返回这样排序的结果:
2 温泉度假村
3 温泉酒店
1 个太空公司
4 备件
表示先包含确切单词然后包含类似单词的项目。
【问题讨论】:
【参考方案1】:您意识到,我猜,您的架构几乎消除了此类查询的索引的任何用处?
一个大问题是您的“LIKE '%spa%'”。任何以通配符开头的“LIKE”键都是自动表扫描。
编辑: 我读到您的问题是说有一个字段名称,其字段值类似于“1 Space Company”、“2 Spa 度假村”等,数字后跟单词。而且您需要在搜索键前面加上通配符才能跳过数字部分。 (这是为了澄清我的第一条评论。)我猜对了吗?
【讨论】:
“1 Space Company”的一个字段值?为什么不是这两个字段——“1”和“Space Company”?仅在名称部分上创建索引是不可能的,而且它显然是两个不同的数据元素,或者您不会询问对部分字段进行排序。 一个大问题是你的“LIKE '%spa%'”。任何以通配符开头的“LIKE”键都是自动表扫描。 我不确定 CHARINDEX('spa ', Name) > 0 会更好。仅仅因为它是表扫描并不意味着它是错误的。我认为无论如何这是一个搜索类型的查询,“Spa”实际上是一个@FindMe 参数。尝试提供帮助而不是吝啬如何? 他正在帮助教导所使用的技术和底层设计是糟糕的。将您的搜索基于这样的查询就像在 Jello 上建立您的家庭基础。 我不同意。扫描类型的查询有时是可以的,只要它有一个狭窄的焦点并且不是主要的搜索方式。哦,是的,另外 - 他错了。【参考方案2】:您基本上需要(精确地)定义您的排名函数到底是什么。如果您有一排是“The Spa”怎么办。或“spa.com”?定义好之后,您需要将该逻辑放入您的 ORDER BY 子句中。例如:
SELECT
name
FROM
Some_Table
WHERE
name LIKE '%spa%'
ORDER BY
CASE
WHEN name LIKE '% ' + @search_word + ' %' THEN 1 -- Notice the spaces
ELSE 2
END,
name
或者,您可以编写一个排名函数并使用它:
SELECT
name
FROM
Some_Table
WHERE
name LIKE '%' + @search_word + '%'
ORDER BY
dbo.GetNameMatchRank(name, @search_word)
在非常大的结果集上的性能可能不会太好,因此这种方法取决于您预期的搜索结果大小。
【讨论】:
【参考方案3】:离开上面的例子,至少在 MSSQL2005 中将 CLUSTERED 更改为 NONCLUSTERED 会使其进行表扫描。 CLUSTERED 为您提供索引查找。看起来它符合问题的条件。
创建表 tblTest(ID INT, colname VARCHAR(20) ) 创建集群索引 tstidx1_tblTest ON tblTest(colname); 插入 tblTest SELECT 1,“太空公司” 插入 tblTest SELECT 2,“温泉度假村” 插入 tblTest SELECT 3,“温泉酒店” 插入 tblTest SELECT 4,“备件” 插入 tblTest SELECT 5,'WithoutTheKeyword' SELECT * FROM tblTest WHERE colname LIKE 'Spa%' ORDER BY DIFFERENCE(colname,'Spa') DESC; 删除表 tblTest【讨论】:
【参考方案4】:类似
Select * from TableName where Name Like 'Spa%'
ORDER BY case when soundex(name) = soundex('Spa') then '1' else soundex(name) end
应该可以正常工作。
其实这样会更好
Select * from TableName where Name Like 'Spa%'
ORDER BY DIFFERENCE(name, 'Spa') desc;
FWIW 我做了一些快速测试,如果“名称”在非集群索引中,SQL 将使用索引并且不进行表扫描。此外,LIKE 似乎比 charindex 使用更少的资源(返回不太理想的结果)。在 sql 2000 上测试。
【讨论】:
你写“soundex(name) = soundex('Spa')”,在 soundex(name) 中的名字是什么,或者我应该这样写吗? 对于您编写的第一个脚本,它总是给我这个错误:“将 varchar 值 'L000' 转换为数据类型 int 时转换失败。” 但是您通过删除前导通配符从根本上改变了问题。 也许,我认为是多余的。阿姆雷尔加里?当我有机会时,我会看看这是否会产生差异。但是,您的答案虽然可能不正确,但可以用一种不那么居高临下的语气来表达,甚至更有帮助。我只是想保护新人。 你在推断我无意暗示的事情。我试图从怀疑中受益,而不是“很明显你甚至没有意识到……”其他回答似乎说至少有几个人是这样读的。虽然这总是一个很好的提醒,要更加努力。【参考方案5】:以下应该做必要的事情,但它效率低下,做两个全表选择,而且它还依赖于你的完全匹配被空格分隔。我认为全文索引会有所帮助,但这有其自身的开销。
select distinct * from
(
Select * from TableName
where CHARINDEX('spa ', Name) > 0
or CHARINDEX(' spa', Name) > 0
Union
Select * from TableName
where Name Like '%spa%'
)
【讨论】:
【参考方案6】:这应该可行:
Select * from TableName where Name Like '%spa%'
ORDER BY Name
【讨论】:
问题是他想按匹配的质量排序,而不是匹配。按名称订购不会做他想做的事。以上是关于如何让一个sql搜索查询更强大?的主要内容,如果未能解决你的问题,请参考以下文章