2016-07-20 2 views
2

그룹, 그룹 멤버 및 데일리 테이블 각각 세 개의 테이블이 있습니다.쿼리 출력에 DENSE_RANK()를 적용하려면

models.py 내가 indiviaully 각 그룹에 의해 불에 총 칼로리를 계산하고 싶었

class Group(models.Model): 

    name = models.CharField(max_length=255, blank=False, null=False) 
    group_type = models.ForeignKey('GroupType',blank=True,default=False) 

    class Meta: 
     db_table = 'groups' 

class GroupMembers(models.Model): 
    group = models.ForeignKey('Group') 
    user = models.ForeignKey('User') 
    status = models.CharField(max_length=20) 

    class Meta: 
     db_table = 'group_members' 
     unique_together = ['group', 'user'] 

class DailyTable(models.Model):  
    class Meta: 
     managed = True 
     db_table = 'dailytable' 

    user_id = models.IntegerField(db_index=True)   
    calories = models.FloatField()   
    date = models.DateField() 

: 아래 그들의 각 하나에 대한 내 모델이다. 그래서 아래의 쿼리 해고 : 아래

select groups.id,groups.name as group_display_name, 
(select count(*) from group_members where group_id = groups.id and status = 'accepted' and groups.group_type_id = 1) as total_members, 
(select sum(calories) from dailytable where user_id in (select user_id from group_members where group_id = groups.id and groups.group_type_id = 1) and dailytable.date='2016-02-02') as total_calories, 
(select case when exists(select * from group_members where group_id = groups.id and user_id = 3 and status = 'accepted' and groups.group_type_id = 1) then cast(1 as bit) else cast(0 as bit) end) as is_member_of_group 
from groups 
where groups.group_type_id = 1 
order by total_calories desc 
nulls last; 

내가 내가 구워 놓은 total_calories에 따라 그룹 순위 싶어 이제 enter image description here 를 얻을 출력입니다, 그래서 쿼리에서 아래의 변경 :

.... 
dense_rank() over(order by total_calories) 
from groups 
.... 

오류 : 열 "total_calories"나는 쿼리의 출력에 RANK을 적용 할

존재하지 않습니다. 이를 달성 할 수있는 방법이 있습니까?

답변

1

dense_rank()에서 파생 열 별칭을 사용하려고했기 때문입니다.이 기능은 사용할 수 없습니다. CTE에서 검색어를 감싸고 dense_rank()를 적용하십시오.

WITH baseQuery AS (
    SELECT 
     groups.id, 
     groups.name AS group_display_name, 
     (
      SELECT 
       count(*) 
      FROM group_members 
      WHERE 
       group_id = groups.id AND status = 'accepted' AND groups.group_type_id = 1) AS total_members, 
     (
      SELECT 
       sum(calories) 
      FROM dailytable 
      WHERE 
       user_id IN (
        SELECT 
         user_id 
        FROM group_members 
        WHERE 
         group_id = groups.id 
         AND groups.group_type_id = 1 
       ) AND dailytable.date = '2016-02-02' 
     ) AS total_calories, 
     (
      SELECT 
       CASE WHEN exists(SELECT 
            * 
           FROM group_members 
           WHERE 
            group_id = groups.id 
            AND user_id = 3 
            AND status = 'accepted' 
            AND groups.group_type_id = 1) 
        THEN cast(1 AS BIT) 
       ELSE cast(0 AS BIT) END) AS is_member_of_group 
    FROM groups 
    WHERE 
     groups.group_type_id = 1 
) 
    select * , 
     dense_rank() over(order by total_calories) 
    from baseQuery 
    ORDER BY total_calories DESC 
    NULLS LAST 
1

검색어를 서라운드하고 외부 선택에서 순위를 계산하십시오.

아래 예에서 쿼리는 하위 쿼리 대신 조인과 그룹을 사용하여 합계를 계산합니다.

select 
q.*, 
DENSE_RANK() over (order by total_calories) as total_calories_rank 
from 
(
    select 
    g.id as group_id, 
    g.name as group_name, 
    count(distinct m.user_id) as total_members, 
    sum(d.calories) as total_calories, 
    cast(max(case when m.user_id = 3 then 1 else 0 end) as bit) as user_3_is_member_of_group 
    from groups g 
    inner join group_members m on (g.id = m.group_id and m.status = 'accepted') 
    left join (
     select user_id, sum(calories) as calories 
     from dailytable 
     where date = '2016-02-02' 
     group by user_id 
    ) d on (m.user_id = d.user_id) 
    where g.group_type_id = 1 
    group by g.id, g.name 
) q 
order by total_calories desc 
nulls last; 
관련 문제