对象型数据库(PG、MySql)中的分组排序
在项目开发中,有时候会遇到“查找依据特定字段分组后,排序topX的数据”这样的需求,在这种情况下,通过sql语句的分组排序即可解决。
postgres数据库
pg自带函数即支持
row_number() over(partition by 分组字段 order by 排序字段 desc)
例如以下,我要在每个同级别的名称中选取一个数据出来
select t.* from (select s.*,row_number() over(partition by level2 order by level2 ) as rwnum from ctis_v_trial_task_all_video s where 1=1
) t where rwnum=1
https://blog.csdn.net/e_wsq/article/details/38072917
mysql数据库
mysql数据库不支持row_number函数。这里为了实现分组排序主要用到了自定义变量和子查询
整体思路是:先在子查询中对于要分组排序的字段通过order by排好序;然后再对变量@row_number赋值时通过case when进行判断赋值
例如以下语句,通过语句SELECT n.site_name, title, news_tag, type, publish_time, gather_time FROM keypoint_news n LEFT JOIN info site ON n.site_name = site.site_name WHERE site.id IN ( 1, 6, 7 ) ORDER BY n.site_name, n.gather_time DESC
形成要查询的临时表s,然后再通过对s的字段的判断来给num指定值SELECT @row_number := CASE WHEN @customer_no = s.site_name THEN @row_number + 1 ELSE 1 END AS num
。最后把所有取出的字段组成一个临时表news,通过对news.num的限定来指定取topX。
整体语句如下:
SELECT siteName, title, tag AS newsTag, type, publish_time AS publishTime, num, gather_time AS gatherTime FROM ( SELECT @row_number := CASE WHEN @customer_no = s.site_name THEN @row_number + 1 ELSE 1 END AS num, @customer_no := s.site_name AS siteName, s.title, s.tag, s.type, s.publish_time, s.gather_time FROM ( SELECT @row_number:=0, @customer_no:='', n.site_name, title, tag, type, publish_time, gather_time FROM info n LEFT JOIN info site ON n.site_name = site.site_name WHERE site.id IN ( 1, 6, 7 ) ORDER BY n.site_name, n.gather_time DESC ) s ) news WHERE news.num < 4
注意这条语句有时候会把所有数据差出来,也就是num都当成1.。。。但是连着两次运行就会分好组排好序。。。不太清楚啥原因————为了解决rownum累加问题
可以通过加入select @row_number:=0, @customer_no:='' 来将变量重置从而解决计算出的rownum累加的问题。(加入此句后,不再需要执行两次)