一、前言
现有一个需求:实现多条件、不确定条件的搜索功能。
类似于淘宝网进行搜索商品的时候,可以在搜索框进行模糊搜索,同时可以进行条件筛选,例如想买一只 口红? 的时候,可以在搜索框内输入“口红”,还可以选择品牌、是否包邮、价格区间等等。。最后搜索出来的结果是满足所有筛选的条件的。
这里我认为的难点就是:这些条件你不确定需不需要,你不确定选了几个,所以说这些都是动态的。
我总结了一句话来进行概括:同类型条件取并集,不同类型条件取交集。
二、前台界面(了解需求)
页面默认加载全部数据
当有搜索条件后,取满足所有条件的数据:试题内容中包括关键字”程序“、试题类型为”判断题“、所属知识点为”关系运算符、对象的概念“。
这里前台使用了easyui框架、下拉框多选技术、easyUI分页技术参考我的这两篇博文:
在本页面可以看出,在所有试卷中,可以通过关键字搜索试题内容,通过复选下拉框筛选”试题类型“、”所属知识点“这两种条件。
三、mybatis sql语句
这个sql涉及到了三张表的查询,其中还包括嵌套查询。写这个之前真的没想到自己能写出这么复杂的sql语句。
暂时还没考察其健壮性,现在就是把功能都实现了。
把sql语句贴出来:
<select id="selectAllQuestions" resultType="java.util.Map">
SELECT <include refid="Extend_Column_List"/>, kp.kp_title as kp_value, sys.code_text as question_type_value
FROM aim_test_questions qt
inner join amc_knowledgepoint_base_t kp
on qt.belong_kpcode = kp.kp_code and qt.question_state = '1'
inner join sys_code_t sys
on sys.code_data = qt.question_type and sys.code_kind_1 = '试题类型'
<where>
<if test="question_content != null and question_content != ''">
and question_content LIKE CONCAT(CONCAT('%',#{question_content}),'%')
</if>
<if test="kp_title!=null and kp_title.size!=0">
and qt.belong_kpcode in (
SELECT kp.kp_code
FROM amc_knowledgepoint_base_t kp
<where>
kp.kp_title in
<foreach collection="kp_title" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</where>
)
</if>
<if test="code_text!=null and code_text.size!=0">
and qt.question_type in (
SELECT sys.code_data
FROM sys_code_t sys
<where>
sys.code_text in
<foreach collection="code_text" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</where>
)
</if>
</where>
order by qt.question_create_time asc
</select>
where前面的不用看,主要看<where>里面有三个<if>。这就是”不同类型条件取交集“,所以这里用到了
<where>
<if>
</if>
<if>
</if>
<if>
</if>
</where>这样的结构来对条件进行筛选。
第一个<if>实现了关键字的模糊搜索。
第二个<if>由于涉及到了另一张表的条件查询,所以用到了嵌套查询。
在前台,下拉框的条件值可以为多个。所以前台会给后台传一个list,其中 kp_title 是用来存放第一个下拉框的值的一个Map。
在这个嵌套语句里面用到了<foreach></foreach>,可以对map、list、array这三种数据类型进行遍历。在本栗子中,
<foreach collection="kp_title" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
collection里面的kp_title为map的key值。item是用来遍历map的value值的一个别名。
第三个<if>与第二个的内容相似,只不过是又多关联查询了第三张表。
四、总结
当时写这个sql语句真可谓是”吭哧瘪肚“呀,哈哈。其实现在想想也不难。重要的是要把需求先捋清楚。
然后mybatis的sql语句不要着急直接往里面写。可以先在数据库里面把sql语句敲一遍,确认无误后,再写mybatis。
遇到像上面这种需求比较多的,可以把需求拆分。例如先把一个模糊搜索的功能实现。然后再实现其他的功能。
感觉当时写这个的时候有点费劲,所以想贴出来给大家分享,如果不对的地方希望各位大牛能多多指正,大家一起交流一起进步。