原文链接:http://www.likezhou.com/find/11681.html
查询各种类型的前n条数据的的sql写法,有好几种:
假设要查询每种分类点击量前三的数据,type为类型字段,clickNum为点击数。
第一种:
select
*
from
table AS a
where
(select COUNT(*) from table AS b where
b.type= a.type
AND
b.clickNum >= a.clickNum) <= 3
ORDER BY a.type_id asc,a.clickNum DESC;
用上面的方法,有一个问题,就是如果记录的点击数刚好有一摸一样的,就容易漏掉数据。而且如果数据量一大,上面的查询性能是非常差的。基本是数据条数的平方这样的量级。比如如果有100条数据,那可能就是要查询10000次。
第二种:是国外某个人写的一种方法,测试过,可以用。
set @num := 0, @type := '';
SELECT * FROM
(SELECT *,
@num := if(@type = type, @num + 1, 1) as row_num,
@type := type
FROM table
order by type ASC,clickNum DESC)
as temp
WHERE temp.row_num <=3;
这个的查询效率就还ok,扫描的量级相比上面是控制在o(n)这种量级,性能提升是很明显的,不过有个问题,如果你用mybatis操作数据库,这个代码貌似运行不成功,或者并没有得到自己想要的结果。具体原因我也不知道,有知道的麻烦告诉我一下。
第三种,我最后采用的方式,就是用union all。写法如下:
(select * from table where type = 'apple' order by price limit 2)
union all
(select * from table where type = 'orange' order by price limit 2)
union all
(select * from table where type = 'pear' order by price limit 2)
union all
(select * from table where type = 'cherry' order by price limit 2)
说白了对每种类型根据你所要条件进行查询,然后用union all进行连接即可。当然我之所以采用这种方式是因为在mybatis里面也可以实现写法,如下
<select id="selectdatabyType" resultMap="ResultMapWithBLOBs" >
<foreach collection="list" item="item" index="index" separator="union all">
(select
<include refid="Base_Column_List" />
from
table where type = ${item.id} and status=1 order by clickNum DESC limit 0,3)
</foreach>
</select>
上面的实现的关键是,记得加()。