Oracle模糊查询按相似度排序并分页思路和mybatis实现
这里先说下大概思路,先进行模糊查询,然后按相似度进行排序,最后进行分页,思路就是这样,很清晰。
一定要看到最后,有本人的无偿贡献!!!可供提升用
说的简单,干起来就难了
第一步 模糊查询
闹它!!!
select e.* from employee e where e.nameen like '%' || 'wangdi' || '%'
查询结果:
这都啥呀我要的是wangdi,一个美丽的小妹妹,这都是wangdi的七大姑八大姨呀,wangdi哪?
咦…加个相似度排序试试吧,闹它!
第二步 相似度排序
这里我研究了两种方法,第一种就是用最笨的Sql里的通配符,第二种使用字段的长度来排序,这个好,SQL语句看起来都清晰,也不费脑子,最重要的是可以使用多个字段进行排序。
虽然通配符繁琐,这里,还是简单介绍下SQL的通配符吧!谁让我人这莫好了呐!
SQL模糊查询的三种通配符
- %:表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。
- _: 表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句。我先就是用这种傻乎乎的方式进行排序的,哎呀啥都说,这也太丢人了
- [ ]:表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。例如:[^ ] 表示不在括号所列之内的单个字符。其取值和 [] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
结果是快乐的,过程是艰辛的
闹它!!!
select e.* from employee e
where e.nameen like '%' || 'wangdi' || '%'
order by nvl(length(trim(e.nameen)),0) asc
这多美好,wangdi小妹妹一下就找到了,哎怎末查咋个name为王晨迪的小弟弟,这太乱了,我可是个专一的人!
闹它!!!
select e.* from employee e
where e.nameen like '%' || 'wangdi' || '%'
order by nvl(length(trim(e.nameen)),0) asc,
nvl(length(trim(e.name)),0) asc
好安逸幺!
第三步 分页
这模糊查询结果太多了,咱们也得给他个限制,那就分页,每页20个,
闹它!!!
select * from (
select my_table.*, rownum as my_rownum from (
select e.* from employee e
where e.nameen like '%' || 'wangdi' || '%'
order by nvl(length(trim(e.nameen)),0) asc,
nvl(length(trim(e.name)),0) asc)
my_table where rownum <=20 )
where my_rownum>=1
前20条都查出来了,wangdi小妹妹也排在前位,安逸不?
上大招
做开发在工具上实现是不行滴,还得要在程序中实现,哎,就弄这个mybatis我是最烦的,没办法,还得要实现呀,不实现怎末把wangdi小妹妹娶回家哪?
闹它!!!
//dao层接口调用查询女朋友()
List<Girlfriend> findGirlfriendPage(@Param("name") String name,
@Param("nameen") String nameEn,
@Param("start") int start,
@Param("end") int end);
//mybatis XMLb编写
<select id="findGirlfriendPage" resultType="com.kangroo.social_hub.bean.Friend">
select * from (
select e1.*, rownum as my_rownum from (
select e.* from information e
<trim prefix="where" prefixOverrides="or|and">
<if test="name!=null and name!=''">
or e.name LIKE '%'||#{name}||'%'
</if>
<if test="nameen!=null and nameen!=''">
or replace((upper(e.nameen)),' ','') like replace(upper ('%'||#{nameen}||'%'),' ','')
</if>
</trim>
<trim prefix="order by" suffixOverrides=",">
<if test="nameen!=null and nameen!=''">
nvl(length(trim(e.nameen)),0) asc,
</if>
<if test="name!=null and name!=''">
nvl(length(trim(e.name)),0) asc,
</if>
</trim>
) e1 where
1=1
<if test="end!=0">
and rownum <= #{end}
</if>
) where
1=1
<if test="start!=0">
and my_rownum >= #{start}
</if>
</select>
详细解释下:
- trim标签中 prefix:内容前添加的(比如:where | order by 等)
prefixOverrides 前边要舍去的"or|and"表示去掉Trim中有效部分的第一个or或者and。
suffixOverrides 后边要舍去的,比如:","去掉有效部分中最后一个“,”。 - replace((upper(e.nameen)),’ ‘,’’):去掉nameen字段中所有的空格,就拿我们的小妹妹wang di来说,去掉空格就成为wangdi.
- nvl(length(trim(e.name)),0) asc:按照name字段长度大小进行升序排序。
需要注意的
一个trim标签中不能出现两次同样的if标签,如下是行不通的,有大神路过,请指点一二
需要将两个if标签放置在两个trim标签中才行,如上mybatis中。