针对黑客排名挑战编写的SQL查询优化

时间:2019-12-28 14:26:13

标签: sql oracle join case

对于黑客等级的SQL挑战,我已编写了产生所需结果的SQL脚本。但是我过多使用了子查询,我想知道代码是否可以优化。以下是SQL挑战的链接 https://www.hackerrank.com/challenges/challenges/problem

简单的挑战细节:

“编写查询以打印每个学生创建的hacker_id,名称和挑战总数。将结果按挑战总数从高到低排序。如果一个以上的学生创造了相同的数字挑战,然后按hacker_id对结果进行排序。如果有多个学生创建了相同数量的挑战,并且计数少于创建的最大挑战数量,则将这些学生从结果中排除。”

这是我为上述挑战编写的代码:

SELECt
   h.hacker_id,
   h.name,
   t.tot_ch 
from
   hackers h,
   (
      Select
         c.hacker_id,
         count(c.challenge_id) Tot_ch 
      from
         challenges c 
      Group by
         hacker_id 
   )
   T,
   (
      SELect
         tot_ch,
         count(tot_ch) DUPS 
      from
         (
            Select
               c.hacker_id,
               count(c.challenge_id) Tot_ch 
            from
               challenges c 
            Group by
               hacker_id 
         )
     group by tot_ch 
   )
   D 
Where
   h.hacker_id = t.hacker_id 
   And d.tot_ch = t.tot_ch 
   AND 
   (
      CASe
         when
            d.dups < 2 
         then
            1 
         ELSE
( 
            case when 
               t.tot_ch = 
               (
                  select
                     MAX(T1.tot_ch) 
                  from
                     (
                        Select
                           c.hacker_id,
                           count(c.challenge_id) Tot_ch 
                        from
                           challenges c 
                        Group by
                           hacker_id 
                     )
                     T1 
               )
            then
               1 
            End
) 
      end
   )
   = 1 
ORDER BY
   t.tot_ch desc, h.hacker_id;

3 个答案:

答案 0 :(得分:1)

您可以使用常见的表表达式将重复的子查询转换为内联视图,可以像查询普通视图一样进行查询:

WITH cteCount AS (SELECT c.HACKER_ID,
                         COUNT(c.CHALLENGE_ID) TOT_CH
                    FROM CHALLENGES c
                    GROUP BY HACKER_ID),
     cteDups AS (SELECT TOT_CH,
                        COUNT(TOT_CH) AS DUPS 
                   FROM cteCount
                   GROUP BY TOT_CH)
SELECT h.HACKER_ID,
       h.NAME,
       t.TOT_CH 
  FROM HACKERS h
  INNER JOIN cteCount t
    ON t.HACKER_ID = h.HACKER_ID
  INNER JOIN cteDups d
    ON d.TOT_CH = t.TOT_CH
  WHERE CASE
          WHEN d.DUPS < 2
            THEN 1
          WHEN t.TOT_CH = (SELECT MAX(TOT_CH)
                             FROM cteCount)
            THEN 1
        END = 1
  ORDER BY t.TOT_CH DESC,
           h.HACKER_ID;

答案 1 :(得分:0)

您可以按以下方式使用analytical function的组合:

Select hacker_id, name, cnt 
from
(Select t.*,
        count(1) over (partition by cnt) as same_cnt,
        Max(cnt) over () as max_cnt
   from
   (Select h.hacker_id, 
           h.name,
           Count(1) as cnt
      From hackers h
      Join challenges c 
        On h.hacker_id = c.hacker_id
  Group by h.hacker_id, h.name) t)
     Where same_cnt = 1 
        or cnt = max_cnt

干杯!

答案 2 :(得分:0)

with 
cte1 as (select hacker_id, count(challenge_id) as challenges_created 
         from Challenges
         group by hacker_id
         order by hacker_id
),
cte2 as (select c.hacker_id, h.name, c.challenges_created 
         from cte1 c 
         left join Hackers h
         on c.hacker_id = h.hacker_id
),
cte3 as (select max(challenges_created) as max_challenges 
         from cte2
),
cte4 as (select challenges_created, count(hacker_id) as  hack_count_same
         from cte2 
         where challenges_created not in(select max_challenges from cte3)
         group by challenges_created
         order by challenges_created
),
cte5 as (select hacker_id, name, challenges_created 
         from cte2
         where challenges_created not in(select challenges_created from cte4 where hack_count_same > 1)
),
cte6 as (select hacker_id, name, challenges_created 
         from cte5
         union all 
         select hacker_id, name, challenges_created 
         from cte2
         where challenges_created  in(select max_challenges from cte3)
         and hacker_id not in(select hacker_id from cte5)
)
         select * 
         from cte6
         order by challenges_created desc, hacker_id;