【问题标题】:Hackerrank Winners chart SQL advance level questionHackerrank 获奖者图表 SQL 高级级别问题
【发布时间】:2022-09-25 14:18:40
【问题描述】:

这是 Hackerrank 为高级 SQL 认证添加的一个新问题。我根本无法解决它。任何人都可以帮忙吗?

有许多比赛,参与者每个人都进行了多次尝试。得分最高的尝试仅被考虑一次。编写查询以列出在每场比赛中排名前 3 的参赛者。如果多个参赛者在每场比赛中得分相同,则他们处于同一排名。

报告 event_id、排名 1 名称、排名 2 名称、排名 3 名称。通过 event_id 订购比赛。共享等级的名称应按字母顺序排列并用逗号分隔。

按 event_id 排序报告

Question image

  • 你试过什么?你在哪里卡住了?需要更多细节才能提供帮助。
  • @chegancasb 老实说,我尝试解决这个问题,但它是如此令人困惑,以至于我什至无法开始思考它。我对 sql 中的排名不太了解
  • 请不要链接到图片 - 将所有相关信息直接发布到您的问题中,最好是可编辑的文本。此外,您发现它“如此混乱以至于我什至无法开始思考它”这一事实是否表明您还没有准备好接受此认证并且需要获得更多经验 - 而不是让别人帮你解决?
  • @NickW 我通过了测试,但无法解决这个问题,所以需要关于如何解决它的建议。对不起,我会记住不发布图像的事情。
  • 看看 DENSE_RANK()。除了partiaion(即分组)和排序(例如:最高分在前),DENSE_RANK 将所有具有相同分数的人放在同一位置,因此您最终可能会得到 1、2、每个类别 2、3、3、3、4 被分组。

标签: sql


【解决方案1】:

以下是您的场景的一些示例数据。参赛者的表,以及所做的尝试。将每个人的尝试放在自己的线路上,这样您就可以看到每个人明显不同的尝试。

create table contestants
(  id int identity(1,1) not null,
   personName nvarchar(10) )

insert into contestants ( personName )
    values ( 'Bill' ), ('Mary'), ('Jane' ), ('Mark')

create table attempts
( id int identity(1,1) not null,
  contestantid int not null,
  score int not null )

insert into attempts ( contestantid, score )
   values
     ( 1, 72 ), ( 1, 88 ), (1, 81 ),
     ( 2, 83 ), ( 2, 88 ), (2, 79), (2,86),
     ( 3, 94 ),
     ( 4, 79 ), (4, 87)

现在,简单的前提是每个参赛者的最佳分数,这是每个参赛者得分的简单 MAX()。

select
        contestantid,
        max( score ) highestScore
    from
        attempts
    group by
        contestantid

以上查询的结果就是最终排名的BASIS。所以我将该查询作为 FROM 源。因此,from 不是表格,而是上述查询的结果,我将其别名为“PreAgg”,用于每个参赛者的预聚合。

select
        ContestantID,
        c.personName,
        DENSE_RANK() OVER ( order by HighestScore DESC ) as FinalRank
    from
        (select
                contestantid,
                max( score ) highestScore
            from
                attempts
            group by
                contestantid ) preAgg
            JOIN Contestants c
                on preAgg.contestantid = c.id

加入参赛者很容易提取名称,但现在看看 DENSE_RANK() 子句。由于没有按分数分组,例如奥运会有一项特定的运动,并且每项运动都有最高的排名,我们不需要“PARTITION”子句。

ORDER BY 子句是您想要的。在这种情况下,来自预聚合查询的 HighestScore 列并希望它按 DESCENDING 顺序排列,因此 HIGHEST 分数位于顶部并向下。 “as”给它最后的列名。

DENSE_RANK() OVER ( order by HighestScore DESC ) as FinalRank

Results
ContestantID   personName   FinalRank
3              Jane         1
1              Bill         2
2              Mary         2
4              Mark         3

现在,如果您只想要一个限制,例如前 3 名,而您实际上有 20 多个竞争对手,只需在 where 类的地方再结束一次

select * from
(
select
        ContestantID,
        c.personName,
        DENSE_RANK() OVER ( order by HighestScore DESC ) as FinalRank
    from
        (select
                contestantid,
                max( score ) highestScore
            from
                attempts
            group by
                contestantid ) preAgg
            JOIN Contestants c
                on preAgg.contestantid = c.id ) dr
    where
        dr.FinalRank < 3

【讨论】:

    【解决方案2】:

    MY Reference table

    /* MYSQL SOLUTION / /使用多个公用表表达式,dense_rank,Join 和 group_concat */

    与 t1 作为 (SELECT *,DENSE_RANK() OVER(PARTITION BY event_id ORDER BY score DESC) AS 'rk' FROM Scoretable),

    t2 AS (SELECT * FROM t1 WHERE rk<=3),

    t3 作为 (SELECT event_id , CASE WHEN rk=1 THEN p_Name ELSE NULL END AS 'first' FROM t2 WHERE rk=1 ),

    t4 作为 (SELECT event_id , CASE WHEN rk=2 THEN p_Name ELSE NULL END AS 'second' FROM t2 WHERE rk=2 ),

    t5 AS (SELECT event_id , CASE WHEN rk=3 THEN p_Name ELSE NULL END AS 'third' FROM t2 WHERE rk=3 ),

    t6 作为 (SELECT t3.event_id , t3.first , t4.second , t5.third FROM t3 JOIN t4 ON t3.event_id = t4.event_id JOIN t5 ON t4.event_id=t5.event_id ORDER BY 1,2,3,4)

    SELECT event_id , GROUP_CONCAT(DISTINCT first) AS 'rank 1' , GROUP_CONCAT(DISTINCT second) AS 'rank 2' , GROUP_CONCAT(DISTINCT third) AS 'rank 3' 从 t6 GROUP BY 1 ORDER BY 1;

    output

    【讨论】:

      猜你喜欢
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多