2016-10-24 2 views
1

최근에 나는 배지를받은 유일한 사용자를 보았습니다.창 기능을 기반으로 행 필터링

호기심, 내가 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 배를 차지합니다. 하위 쿼리를 사용하면 개선되지 않습니다.


나는 당신이 두 번째 쿼리에 where awarded = 1window function in a where or having clause를 사용하거나 말할 수없는 것을 알고 있습니다.

CTE 또는 하위 쿼리가 없어도 더 빠르고 간단한 쿼리가 있습니까? 나는 (CTE와 함께) 하나를 내 대답으로 주지만 다른 해결책을보고 싶다.

답변

0

하나의 솔루션은 CTE로 group by/having 쿼리를 타고 배지와 사용자 테이블 (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 
에 가입하는 것입니다