SQL匹配多字段进行排序,搜索
谈到搜索,一般就想起了SQL Server的FullTextSearch(全文搜索)功能,它确实强大,但使用起来也要做一些较为繁琐的准备工作,一般小型的项目或者对搜索要求(包括性能需求)不是很高的情况下实用它还是有点太重型了。简单的搜索用SQL查询即可,但一般面临的一个问题就是如何对搜索结果按匹配字段进行优先级排序。
例如有个产品表(Products),它的字段包:括产品ID、产品名称、产品类别、产品品牌、产品简介、产品详细介绍。
字段 | 类型 |
ProdID | int |
ProdName | nvarchar |
CategoryName | nvarchar |
ProdBrand | nvarchar |
ProdIntro | nvarchar |
ProdDescription | nvarchar |
现在我们要求通过某个关键字从Products表中搜索包含该关键字的记录,凡是以下任何一个字段包含该关键字的记录都列出来:ProdName, CategoryName , ProdBrand, ProdIntro, ProdDescription。 并且搜索结果按照前述字段的匹配优先级进行排序:
1)先列出字段ProdName匹配关键字的记录,然后列出字段CategoryName匹配关键字的记录,依此类推,最后列出字段ProdDescription匹配关键字的记录;
2)在字段ProdName匹配关键字的所有记录中,先列出字段CategoryName也匹配关键字的记录,然后列出字段ProdBrand也匹配关键字的记录,依次类推…
3)按照规则2递归排序每个记录分组……
搜索匹配该关键字的所有记录的SQL语句倒很简单:
- SELECT *
- from Products
- WHERE ProdName like '%KeyWord%' or CategoryName like '%KeyWord%' or ProdBrand like '%KeyWord%' or ProdIntro like '%KeyWord%' or ProdDescription like '%KeyWord%'
但对搜索出的结果进行匹配优先级排序稍微有点困难。在用简单的SQL进行搜索时有两种方式来达到这个排序的目的:加权法和多字段排序法(我瞎取的名字^-^)。
一、加权法
对搜索的每条记录计算出一个排序权值来,然后将所有搜索结果按照这个排序权值进行降序排列即可。每条被搜索出的记录的排序权值为该记录所有字段的权值之和。某个字段的权值取决于该字段是否匹配关键字,如果不匹配则为0,如果匹配则为改字段的匹配权值。字段的匹配权值计算方式为:
fieldPriority = 2的i次冥(i为该字段在所有被搜索的字段优先级排序中倒排的位置)
例如,在我们示例中各字段的匹配权值为:
字段 |
倒排位置 |
匹配权值 |
ProdName |
4 |
16 |
CategoryName |
3 |
8 |
ProdBrand |
2 |
4 |
ProdIntro |
1 |
2 |
ProdDescription |
0 |
1 |
之所以采用这种算法,是为了确保某个字段匹配的记录的排序权值不会低于另外一条不匹配该字段但后续字段都匹配的记录的排序权值。例如记录A中仅仅ProdName匹配关键字,所以它的排序权值为16,而记录B中除了字段ProdName外其他字段都匹配,则其排序权值为15(8+4+2+1=15)。但记录A仍然会排在记录B前面。
相应的SQL大致如下:
- SELECT *, (
- (case when charIndex(ProdName,KeyWord)>-1 then 16 else 0 end) +
- (case when charIndex(CategoryName,KeyWord)>-1 then 8 else 0 end) +
- (case when charIndex(ProdBrand,KeyWord)>-1 then 4 else 0 end) +
- (case when charIndex(ProdIntro,KeyWord)>-1 then 2 else 0 end) +
- (case when charIndex(ProdDescription,KeyWord)>-1 then 1 else 0 end)
- ) as OrderPriority
- from Products
- WHERE ProdName like ‘%KeyWord%' or
- CategoryName like ‘%KeyWord%' or
- ProdBrand like ‘%KeyWord%' or
- ProdIntro like ‘%KeyWord%' or
- ProdDescription like ‘%KeyWord%'
- Order by OrderPriority desc
二、多字段排序法
加权法实在是有点啰嗦,倒不如直接利用SQL可以对多个字段进行排序来实现更清晰更直接。实际上我们把每个字段是否匹配的权值分散到SQL的Order里即可,大致SQL如下:
- SELECT *
- from Products
- WHERE ProdName like ‘%KeyWord%' or
- CategoryName like ‘%KeyWord%' or
- ProdBrand like ‘%KeyWord%' or
- ProdIntro like ‘%KeyWord%' or
- ProdDescription like ‘%KeyWord%'
- Order by (case when charIndex(ProdName,KeyWord)>-1 then 0 else 1 end),
- (case when charIndex(CategoryName,KeyWord)>-1 then 0 else 1 end),
- (case when charIndex(ProdBrand,KeyWord)>-1 then 0 else 1 end),
- (case when charIndex(ProdIntro,KeyWord)>-1 then 0 else 1 end),
- (case when charIndex(ProdDescription,KeyWord)>-1 then 0 else 1 end)
SQL匹配多字段进行排序,搜索相关推荐
- mybatis动态查询(分页排序搜索)+分解关联查询+Logback 日志配置(打印sql到控制台)+mybatis新增记录后返回自增的id。批量=11/2~11/20
一.mybatis动态查询(分页排序搜索) mybatis框架分页实现,有几种方式,最简单的就是利用原生的sql关键字limit来实现,还有一种就是利用interceptor来拼接sql,实现和lim ...
- oracle+sql+按中文拼音排序,Oracle 中文字段进行排序的sql语句
Oracle 中文字段进行排序的sql语句 1)按笔画排序 select * from Table order by nlssort(columnName,'NLS_SORT=SCHINESE_STR ...
- SQL char字段类型排序
我是做的ACCESS时候需要对字段的值进行排序,字段格式是char类型的,但是存的值是数字.现在需要对该字段进行排序. 通过查找,找到以下两种方法,记录下来. 1. 你可以转换成int型再排序 sel ...
- SQL Server 使用全文索引进行页面搜索
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/全文索引 概述 全文引擎使用全文索引中的信息来编译可快速搜索表中的特定词或词组的全文查询.全文索引将有关重要的词及其位置的信息存储 ...
- iOS-高仿通讯录之商品索引排序搜索
概述 TableView添加右侧索引, 将数据按照索引分组排序, 并添加搜索功能且在搜索界面复用当前页面. 详细 代码下载:http://www.demodashi.com/demo/10696.ht ...
- oracle排序非英文最后,Oracle中中文、数字,英文混杂形式的字段进行排序的方法...
http://blog.csdn.net/p451933505/article/details/9272257 对Oracle中中文.数字.英文混杂形式的字段进行排序的方法: 例如: order by ...
- LINQ找出重复和不重复的元素及linq OrderBy 方法 两个字段同时排序有关问题
//重复元素:3,4,5 //不重复元素:1,8,9 int[] arr = { 1, 3, 3, 3, 4, 5, 4, 5, 8, 9, 3 };//不重复元素 var unique = arr. ...
- sql 获取数据库字段信息_使用DBATools获取SQL数据库详细信息
sql 获取数据库字段信息 In the series of articles on DBATools, (see TOC at the bottom) we are exploring useful ...
- MySQL order by基于不同字段条件排序
MySQL order by基于不同字段条件排序 从数据库上查询数据的时候,按要求排序,在某个字段的不同值的基础上再选择不同的字段进行排序,具体描述如下: 1:首先有一个基础字段status ,sta ...
最新文章
- Android运行时异常“Binary XML file line # : Error inflat
- 莫斯科保卫战之PHP-502 Bad Gateway
- Winform中实现设置ZedGraph的GraphPane的大小匹配ZedGraphControl
- FastDFS分布式文件系统工作原理
- 高中计算机网络安全教案,浙教版高中信息技术教案信息安全
- python文件路径操作及pathlib库
- bootstrap-select采坑
- iops 条带深度 队列深度 NCQ
- 在linux安装requests库命令,在Linux--Ubuntu18.04环境下安装requests库
- 基于SSM校园一卡通管理系统
- 秒跳转html代码,5秒定时跳转指定网页源码
- Python提取docx格式Word文档中所有尾注
- windows的消息传递--消息盒子
- 你中招了吗?《心理学常见误区》
- Chapter3:字符串编码和文件操作
- Windows上查看CUDA是否安装成功
- Apache POI操作Excel文件
- 双粗虚线中间一条实线_马路上实线两边有很粗的虚线(中间实线或虚线两边还有很粗的虚线是啥意思)...
- OpenSSL SSL_read: Connection was reset, errno 10054
- Git 分支合并情况