首页 新闻 赞助 找找看

【SQL】分组top N

0
悬赏园豆:100 [已关闭问题] 关闭于 2015-02-06 13:01
SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] WHERE [Id] IN
(SELECT [Id] FROM
(SELECT [RK] = ROW_NUMBER() OVER(PARTITION BY [GroupId] ORDER BY [Id] DESC),[Id] FROM [Users]) AS t
WHERE t.[RK] <= 10) ORDER BY [GroupId]

主键id,索引groupid

以上sql 在150w数据 查询时间2s

各位看官可有更优化的方案

FClouds的主页 FClouds | 初学一级 | 园豆:145
提问于:2015-02-02 10:33
< >
分享
所有回答(5)
0

目测没有,马克

ayiis | 园豆:356 (菜鸟二级) | 2015-02-02 10:54
0

子查询后left join目测比in更快。还有你的业务允许脏读吗?加上WITH(NOLOCK)在特定条件下有性能提升。

JeffWong | 园豆:2328 (老鸟四级) | 2015-02-02 11:33

有一些提升,但是微乎其微

支持(0) 反对(0) FClouds | 园豆:145 (初学一级) | 2015-02-03 11:36
0

尽量不要用 in 和not in 很影响效率的,可以改为 exists 和not exists

SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] as u WHERE
Exists (SELECT 1 FROM (SELECT [RK] = ROW_NUMBER() OVER(PARTITION BY [GroupId] ORDER BY [Id] DESC),[Id] FROM [Users]) AS t
WHERE t.[RK] <= 10 AND t.[Id]=u.[Id]) ORDER BY [GroupId]

ku:k | 园豆:162 (初学一级) | 2015-02-02 16:27

性能损失都在排序上面

in查询影响比较小,优化后能少几十毫秒

支持(0) 反对(0) FClouds | 园豆:145 (初学一级) | 2015-02-03 11:33
0

可以试试将子查询改成左表,然后join 你的Users表,而且,貌似不需要用row_number吧。

 

declare @MaxGroupId int
select top 10 @MaxGroupId = [GroupId] from [Users]
group by [GroupId]
order by [GroupId] DESC

SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] WHERE [GroupId] >= @MaxGroupId

抱歉,没看仔细,以上代码更改了题意。
幻天芒 | 园豆:37175 (高人七级) | 2015-02-03 09:28

你的两个表都是User表,为什么还要去in一次呢?直接在子查询里面多查询几个字段就好了哇。

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2015-02-03 09:40

@幻天芒: 子查询字段越多越慢,因为全表扫描了,分区跟ROW_NUMBER()都是全表的,只查主键是最快的

支持(0) 反对(0) FClouds | 园豆:145 (初学一级) | 2015-02-03 11:34

@FClouds: 那就把in去掉,把你子查询的结果用来做主表(左表),关联(inner join)Users表做查询

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2015-02-03 11:39
0

left join会更快,in 的话尽量别用

茂茂 | 园豆:2892 (老鸟四级) | 2015-02-03 16:13
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册