如何让一个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搜索查询更强大?的主要内容,如果未能解决你的问题,请参考以下文章

让 SQL 查询更高效

如何让Charles抓包功能更强大?

如何让SQL成为你很好的查询工具

如何使用一个 SQL 查询从数据库中删除所有表?

如何使用交叉连接优化 SQL 查询

Adaptive Execution如何让Spark SQL更高效更好用