对于黑客等级的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;
答案 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;