使用冒泡排序从两列中选择唯一玩家的分数
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 的分数是如何不正确的。正确的分数应该是 30
、31
(分别是持续时间和步数)。 cow@guy.com 应该显示 31
、35
(分别为持续时间和移动次数)
最后,在 email 列上选择 distinct 在这里也不起作用,例如:http://sqlfiddle.com/#!9/0b1530/4
我已经尝试了几个 JOIN,但我无法使它们正常工作,也无法保持行奇偶校验。
更新 #1
- 最高分是先最低
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
更新#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
如果不在意提交时间,可以去掉外层的嵌套表达式:
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
我遇到了一个非常有趣的挑战,要么是我太认真了(并且错过了一个简单的解决方案),要么是它比我想的要复杂得多嘿
本质上,我有一个跟踪分数的游戏。名为 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 的分数是如何不正确的。正确的分数应该是 30
、31
(分别是持续时间和步数)。 cow@guy.com 应该显示 31
、35
(分别为持续时间和移动次数)
最后,在 email 列上选择 distinct 在这里也不起作用,例如:http://sqlfiddle.com/#!9/0b1530/4
我已经尝试了几个 JOIN,但我无法使它们正常工作,也无法保持行奇偶校验。
更新 #1
- 最高分是先最低
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
更新#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
如果不在意提交时间,可以去掉外层的嵌套表达式:
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