使用冒泡排序从两列中选择唯一玩家的分数

Selecting unique players' scores from two columns with bubble sorting

我遇到了一个非常有趣的挑战,要么是我太认真了(并且错过了一个简单的解决方案),要么是它比我想的要复杂得多嘿

本质上,我有一个跟踪分数的游戏。名为 scores 的 table 包含以下列:

id (pk, ai), email, name, duration, moves

一个玩家(通过电子邮件识别)可以有多行。为了确定获胜者,我们对持续时间应用冒泡排序然后移动。挑战在于:我们如何获得唯一的获奖者名单(通过电子邮件)?

GROUP BY 没有按预期工作,因为这是一个聚合。我们需要在持续时间和移动之间保持对等。

下面是架构和问题的示例:http://sqlfiddle.com/#!9/0b1530/2 -- 请注意相同的电子邮件如何按预期显示。

这个例子使用了 GROUP BY,但是它选择了错误的数据:http://sqlfiddle.com/#!9/0b1530/3——注意 baz@biz.com 的分数是如何不正确的。正确的分数应该是 3031(分别是持续时间和步数)。 cow@guy.com 应该显示 3135(分别为持续时间和移动次数)

最后,在 email 列上选择 distinct 在这里也不起作用,例如:http://sqlfiddle.com/#!9/0b1530/4

我已经尝试了几个 JOIN,但我无法使它们正常工作,也无法保持行奇偶校验。


更新 #1

email         name      duration   moves
foo@bar.com   foo bar   20         36
baz@biz.com   baz biz   30         31
cow@guy.com   cow guy   31         35

更新#2

由于 JSFiddle 的限制,我已将所有内容移至 https://www.db-fiddle.com/f/vV7XMKkoFaynYEajLtYm9h/2

请注意,您答案中的某些查询不起作用。我在这里使用了真实数据(除了更改 emails/names)以便答案可以测试真实数据。

以下是此示例数据的预期结果:

email           duration    moves
dp@dp.com       32          22
bw@bw.com       33          21
m@m.com         38          23
s@s.com         40          25
foo@bar.com     41          22

我想你想要每个玩家的分组最短持续时间,然后是每个分组的最短移动。

SELECT  s.email, s.duration, MIN(s.moves)
FROM    scores s
LEFT OUTER JOIN scores s_min ON s.email = s_min.email
  AND s.duration > s_min.duration
WHERE  s_min.id IS NULL
GROUP BY s.email, s.duration
ORDER BY s.duration, MIN(s.moves)

这是显示获胜者的fiddle:http://sqlfiddle.com/#!9/0b1530/56

foo@bar.com 20  36
baz@biz.com 30  31
cow@guy.com 31  35

一种方法是使用两个嵌套的 IN 表达式。内部表达式查找电子邮件和持续时间的所有组合,这些组合具有该电子邮件的最短持续时间。外部表达式然后找到电子邮件、持续时间和移动值,这些值是该持续时间的最低移动值(对于该电子邮件而言是最低的)。

SELECT *
FROM scores
WHERE (email, duration, moves) IN (
    SELECT email, duration, MIN(moves)
    FROM scores
    WHERE (email, duration) IN (
        SELECT email, MIN(duration)
        FROM scores
        GROUP BY email)
    GROUP BY email, duration)
ORDER BY duration, moves

输出:

id      email           name        duration    moves   submitted
219     foo@bar.com     foo bar     20          36      2019-12-09T20:36:19Z
224     baz@biz.com     baz biz     30          31      2019-12-09T20:36:19Z
233     cow@guy.com     cow guy     31          35      2019-12-09T20:36:19Z

Demo on SQLFiddle

如果不在意提交时间,可以去掉外层的嵌套表达式:

SELECT email, name, duration, MIN(moves) AS moves
FROM scores
WHERE (email, duration) IN (
    SELECT email, MIN(duration)
    FROM scores
    GROUP BY email)
GROUP BY email, name, duration
ORDER BY duration, moves

输出:

email           name        duration    moves
foo@bar.com     foo bar     20          36
baz@biz.com     baz biz     30          31
cow@guy.com     cow guy     31          35

Demo on SQLFiddle

Demo with full data on dbfiddle