确保min()仅检索一个值

时间:2012-08-29 19:36:44

标签: sql sql-server-2000

我有一个SQL查询,可以从列出运动员100米和200米比赛时间的表格中检索数据。该查询仅根据athlete_id检索每位运动员的最佳比赛时间,并且还想知道比赛时间是100或200米(event_code)。

所以跑步者可以有几个比赛时间但是每次比赛时每个跑步者的查询只能获得最佳比赛时间。

问题在于,如果运动员完成两次或更多次最佳比赛时间,则查询将检索所有比赛时间。如何确保查询仅检索一个值?

以下是代码:

select r.*
from result r
inner join (
    select athelete_id, min(result_time) as FastestTime
    from result
    where event_code = 1
    group by athelete_id
) rm on r.athelete_id = rm.athelete_id and r.result_time = rm.FastestTime

3 个答案:

答案 0 :(得分:1)

对不起,我有点误解了这个问题,但你可以像这样对所有这样的竞争对手进行管理:

 select MIN(r.id), r.athelete_id, r.result_time, r....
    from result r
    inner join (
        select athelete_id, min(result_time) as FastestTime
        from result
        where event_code = 1
        group by athelete_id
    ) rm on r.athelete_id = rm.athelete_id and r.result_time = rm.FastestTime
    GROUP BY r.athelete_id, r.result_time, r.... 
--(as how many column you have, except r.ID)

试试这个:

select top 1 r.*
from result r
inner join (
    select athelete_id, min(result_time) as FastestTime
    from result
    where event_code = 1
    group by athelete_id
) rm on r.athelete_id = rm.athelete_id and r.result_time = rm.FastestTime

OR

SET ROWCOUNT 1

    select r.*
    from result r
    inner join (
        select athelete_id, min(result_time) as FastestTime
        from result
        where event_code = 1
        group by athelete_id
    ) rm on r.athelete_id = rm.athelete_id and r.result_time = rm.FastestTime

答案 1 :(得分:1)

这在SQL Server 2000中很痛苦。使用row_number会更容易,但这需要2005年。

但是,这个想法很简单,你只需要再多一层子查询:

select r.*
from result r join
     (select r.athelete_id, MIN(result_id) as minresult_id
      from result r inner join
           (select athelete_id, min(result_time) as FastestTime
            from result
            where event_code = 1
            group by athelete_id
           ) rm
           on r.athelete_id = rm.athelete_id and r.result_time = rm.FastestTime
      group by r.athelete_id
     ) aft
     on r.result_id = minresult_id

最里面的子查询基本上是你的子查询。然后,这由athelete_id汇总,以获得用于最终连接的最小result_id。

答案 2 :(得分:0)

与戈登相似的方法大致相同,但是使用最早的事件(应该是标识列,如果那是result_id,那就打破了联系),但这并不总能得到保证。

DECLARE @event_code INT;
SET @event_code = 1;

SELECT r.*
FROM dbo.result AS r 
INNER JOIN 
(
  SELECT r2.athelete_id, x.mintime, mindate = MIN(r2.result_date)
    FROM 
    (
      SELECT athelete_id, mintime = MIN(result_time)
      FROM dbo.result
      WHERE event_code = @event_code
      GROUP BY athelete_id
    ) AS x
    INNER JOIN dbo.result AS r2
    ON x.athelete_id = r2.athelete_id
    AND x.mintime = r2.result_time
    WHERE r2.event_code = @event_code
    GROUP BY r2.athelete_id, x.mintime
) AS y
ON r.athelete_id = y.athelete_id
AND r.result_time = y.mintime
AND r.result_date = y.mindate
WHERE r.event_code = @event_code;

当然,SQL Server 2005要容易得多:

;WITH x AS 
(
  SELECT athelete_id, --... other columns, 
    rn = ROW_NUMBER() OVER (PARTITION BY athelete_id ORDER BY result_time, result_date)
  FROM dbo.result
  WHERE event_code = 1
)
SELECT athelete_id, --... other columns
FROM x WHERE rn = 1;