我有两个桌子 playersscores.

我想生成一个看起来像这样的报告:

player    first score             points
foo       2010-05-20              19
bar       2010-04-15              29
baz       2010-02-04              13

现在,我的查询看起来像这样:

select p.name        player,
       min(s.date)   first_score,
       s.points      points    
from  players p    
join  scores  s on  s.player_id = p.id    
group by p.name, s.points

我需要 s.points 与该行有关 min(s.date) 返回。这个查询发生了吗?也就是说,我怎么能确定自己得到了正确的 s.points 连接行的价值?

旁注:我想这与MySQL缺乏密集排名有关。这里最好的解决方法是什么?

有帮助吗?

解决方案

这是堆栈溢出经常出现的最大的每组问题。

这是我通常的答案:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and s2.date < s.date

where
  s2.player_id is null

;

换句话说,给定得分S,尝试为同一玩家找到分数S2,但日期较早。如果找不到较早的分数,那么S是最早的分数。


您对关系的评论:您必须制定一项政策,以防平局。一种可能性是,如果您使用自动插入主键,则值最少的是较早的键。请参阅下面的外部联接中的附加术语:

select
  p.name        player,
  s.date        first_score,
  s.points      points

from  players p

join  scores  s
  on  s.player_id = p.id

left outer join scores  s2
  on  s2.player_id = p.id
      and (s2.date < s.date or s2.date = s.date and s2.id < s.id)

where
  s2.player_id is null

;

基本上,您需要添加决胜术语,直到您到达至少对于给定玩家的列来保证是唯一的。表的主要键通常是最好的解决方案,但是我已经看到了另一列是合适的情况。

关于我与@OMG Ponies分享的评论,请记住,这种类型的查询从正确的索引中受益匪浅。

其他提示

使用组时,大多数RDMBS甚至都不会让您在选择子句中包含非聚合列。在MySQL中,您最终会从随机行中获得非聚合列的随机行。如果您在所有行中的特定列中实际上具有相同的值,这将很有用。因此,MySQL不限制我们,尽管要理解这是一件重要的事情,这真是太好了。

整章专门针对此 SQL反植物.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top