根据窗口函数过滤行

时间:2016-10-24 20:49:32

标签: sql sql-server

最近,我看到一位用户,他是唯一获得一些徽章的用户。

奇怪的是,我前往data.se寻找类似的例子(data.se - Single awarded badges

select count(*) as awarded,
       name, class
from badges
group by name, class
having count(*) = 1

更进一步,我还希望看到拥有这些徽章的用户(data.se - Count awarded badges and users

select count(*) over (partition by b.name, b.class) as awarded,
       b.name, b.class, u.displayname
from badges b
join users u on u.id = b.userid

这给了我所有条目,而不仅仅是单个条目,例如: count(*) = 1。要获得这些,我必须使用CTE或子查询,例如(data.se - Single awarded badges and users

with q as (select count(*) over (partition by b.name, b.class) as awarded,
                  b.name, b.class, u.displayname
           from badges b
           join users u on u.id = b.userid)
select name, class, displayname
from q
where awarded = 1

最后两个查询的缺点是性能。 (非缓存)查询大约需要简单group by/having查询的20倍。使用子查询没有任何改进。

我知道,您无法使用window function in a where or having clause,也无法在第二个查询中说where awarded = 1

是否有更快更简单的查询,甚至可能没有CTE或子查询?我给一个(用CTE)作为我自己的答案,但是希望看到替代解决方案。

1 个答案:

答案 0 :(得分:0)

一种解决方案是将group by/having查询作为CTE并加入徽章和用户表(data.se - Single awarded badges and users

with awarded as (select count(*) as num,
                        name, class
                 from badges
                 group by name, class
                 having count(*) = 1)
select b.name, b.class, u.displayname
from badges b
join awarded a on a.name = b.name and a.class = b.class
join users u on u.id = b.userid