【问题标题】:Return highest number from distinct date返回不同日期的最大数字
【发布时间】:2012-04-19 14:16:47
【问题描述】:

数据:

Name | Score | Date
==
John | 10 | 09/01/2012
John | 20 | 09/01/2012
John | 5 | 09/01/2012
Frank | 20 | 11/01/2012

我想运行一条 SQL 语句,它只提取每天的最高分数,所以我不想要一个日期的三个分数,只有最高分数。所以我想从 SQL 得到的回报是:

John  | 20 | 09/01/2012    
Frank | 20 | 11/01/2012

是否可以通过 SQL 执行此操作,目前我可以在通过检查日期提取所有内容后执行此操作。但如果可以直接从数据库中进行,那就太好了。

我尝试了一些解决方案,但由于日期和分数并不明显,因为我想要最高的,我不确定从哪里开始。 SQL 正在与 MS Access 数据库一起使用。

【问题讨论】:

  • 这里有歧义。如果 2012 年 9 月 1 日的数据是针对三个不同名称的,您希望返回什么?日期、该日期的高分以及与该高分匹配的名称?另外,如果两个不同的名字在同一天都有相同的最高分怎么办?
  • 谢谢大家。两种解决方案都应该有效。
  • 通过编辑,他们有不同的行为,因为你没有指定如果两个不同的人在同一天得分,和/或如果他们并列,应该发生什么应该最高分。
  • @Dems 公平点。这将是每个日期的最高记录。但我认为你的观点是 2 相同的分数。

标签: sql ms-access group-by


【解决方案1】:

这是一个完整的例子。我是在 Oracle 中完成的,因此您可能需要稍微调整一下 Access 的语法。

CREATE TABLE tbl1 (NAME VARCHAR2(100), score INT, Dt DATE);

INSERT INTO tbl1 VALUES ('John',10,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',5,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Harry',15,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Frank',20,to_date('20121101','YYYYMMDD'));


select a.dt
     , b.name
     , a.score
  FROM (SELECT dt
             , MAX(score) score
          FROM tbl1
       GROUP BY dt) a
     , (SELECT NAME
             , dt
             , MAX(score) score
          FROM tbl1
       GROUP BY name, dt) b
  WHERE a.dt = b.dt
    AND a.score = b.score       

输出:

1   11/1/2012   Frank   20
2   9/1/2012    John    20

请注意,如果两个人在某一天的得分最高,它将打印他们两个。例如:

INSERT INTO tbl1 VALUES ('John',10,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',5,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Harry',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Frank',20,to_date('20121101','YYYYMMDD'));


select a.dt
     , b.name
     , a.score
  FROM (SELECT dt
             , MAX(score) score
          FROM tbl1
       GROUP BY dt) a
     , (SELECT NAME
             , dt
             , MAX(score) score
          FROM tbl1
       GROUP BY name, dt) b
  WHERE a.dt = b.dt
    AND a.score = b.score       

输出:

    DT          NAME    SCORE
1   11/1/2012   Frank   20
2   9/1/2012    John    20
3   9/1/2012    Harry   20

【讨论】:

  • +0 :您的第二个答案似乎最接近 OP 用英文描述的内容。但是,示例输出还包括与当天最高分相关联的名称。您没有包含该名称。
  • @Dems - 是的,你是对的。感谢您指出。我正在修改答案。
  • @Dems - 请检查修改后的答案,让我知道您的想法,谢谢。
  • 第二个子查询可以是tbl1,加入会保证你每天只得到一个分数。但是,是的,这有效,据我了解 OP 的问题。 [虽然,我只赞成使用 ANSI-92 JOIN 语法的答案,而不是 ,'s,对不起。]
  • 这是一个更好的解决方案。所以它可以有一个平局和一个以上的高分。谢谢。
【解决方案2】:

我想这很简单

Select [Name], max([score]) as Score, [Date] from scoresTable
   group by [Date], [Name]

编辑:

更准确但有点复杂

select o.[Name], i.[Date], i.Score from scoresTable o
inner join (select [Date], max(Score) as Score
   from scoresTable group by [Date]) as i
on o.[Date] = i.[Date] and i.Score = o.Score

更重要的是,如果您的日期字段也包含时间

select o.[Name], i.[Date], i.Score from scoresTable o
inner join (select convert(varchar, [Date], 101) as Date, max(Score) as Score
  from scoresTable
    group by convert(varchar, [Date], 101)) as i
on convert(varchar, o.[Date], 101) = i.[Date] and i.Score = o.Score

【讨论】:

  • 这里有一个假设,它确实 not 匹配 OP 用英文写的内容。也就是说,OP 只需要每个日期一条记录,并且每个日期每个名称返回一条记录。 [如果 09/01/2012 的数据是针对三个不同的人,则只应返回一条记录,您返回 3。]
  • I want to run an SQL statement that will pull only the highest score from each day only, so I don't want three scores from one date, only the highest. 我很清楚 OP 想要每天一条记录。示例输出包含一个名称字段,但我将其解释为与最高分数相关联的名称,否则它将与上面的引用冲突。此外,如果您回答的问题让您感觉不明确,那么您应该指定您正在使用的假设。
  • 别名,忘记了。谢谢。
  • @Dems -“我很清楚,OP 每天需要一条记录”您忘记了每天有 2 个(或更多)名称得分最高的情况(请参阅我的回答详细信息和示例)。顺便说一句,我确实在我的回答中指定了这个假设:)。
  • 为什么要将日期转换为字符串?它会降低 JOIN 的性能,因为它无法使用索引查找。 [如果日期需要格式化,请在客户端中进行,如果必须,则在外部查询中进行,但在内部查询中不需要;出于性能原因。]
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多