SQL Server - 在上一个日期不为空时获取最高值

时间:2012-10-25 15:16:11

标签: sql sql-server

我有一个表格,其中包含玩家在任何一天所采取步骤的信息,我想从数据库中获得3个最高总数,当高总数的前一天为该玩家添加了一个值时。由于有些玩家不是每天都在记录,而是将多天的时间归结为一次更新。

数据结构:

|---------------------------------------------------------------|
| id | player_id | steps | date       | submitted               |
|----|-----------|-------|------------|-------------------------|
| 1  | 16        | 5718  | 2012-09-06 | 2012-09-10 08:31:35.000 |
| 2  | 16        | 9837  | 2012-09-07 | 2012-09-10 08:31:17.000 |
| 3  | 16        | 10432 | 2012-09-09 | 2012-09-10 08:30:54.000 |
| 4  | 30        | 3973  | 2012-09-07 | 2012-09-10 09:34:42.000 |
| 5  | 30        | 7104  | 2012-09-08 | 2012-09-10 09:35:05.000 |
| 6  | 30        | 10916 | 2012-09-09 | 2012-09-10 09:35:29.000 |
| 7  | 9         | 6437  | 2012-09-07 | 2012-09-10 09:39:15.000 |
| 8  | 9         | 9032  | 2012-09-08 | 2012-09-10 09:40:02.000 |
|---------------------------------------------------------------|

所以我要返回的是行:

|---------------------------------------------------------------|
| 6  | 30        | 10916 | 2012-09-09 | 2012-09-10 09:35:29.000 |
| 2  | 16        | 9837  | 2012-09-07 | 2012-09-10 08:31:17.000 |
| 8  | 9         | 9032  | 2012-09-08 | 2012-09-10 09:40:02.000 |
|---------------------------------------------------------------|

我的查询目前是:

SELECT TOP 3 p.name,
             player_id,
             steps,
             date
FROM   steppers_step_log
       JOIN steppers_players P
         ON player_id = P.id
ORDER  BY steps DESC 

其中没有考虑到前三个步骤中的日期条目,以我当前形式的查询将返回10432,10916和9837作为顶部步骤。

我无法弄清楚如何执行WHERE命令以确保前一天有该player_id的条目,并希望获得任何帮助以使其正常工作。

3 个答案:

答案 0 :(得分:3)

这样的东西?

SELECT TOP 3 p.name,
             player_id,
             steps,
             date
FROM   steppers_step_log
       JOIN steppers_players P
         ON player_id = P.id
WHERE EXISTS
(
   SELECT 1 FROM steppers_step_log ssp
   WHERE ssp.player_id = P.id
   AND date = DATEADD(day, -1, steppers_step_log.date)
)
ORDER  BY steps DESC 

DATEADD (Transact-SQL)

答案 1 :(得分:1)

您只需使用WHERE条件添加EXISTS子句......

SELECT TOP 3
  p.name,
  player_id,
  steps,
  date
FROM
  steppers_step_log    AS log
INNER JOIN
  steppers_players     AS players
     ON log.player_id = players.id
WHERE
  EXISTS (
    SELECT *
      FROM steppers_step_log
     WHERE player_id = players.id
       AND date      = log.date - 1
  )
ORDER BY
  log.steps DESC 

这个可以但是,不止一次返回同一个玩家;如果他们在前3名中有多个参赛作品。这就是你想要的吗?

答案 2 :(得分:1)

有几种方法可以解决这个问题。其他人可能会使用join / exists类型查询来执行解决方案。我喜欢使用排名函数来获取适当行的替代方法。

您正在寻找的是上传序列,然后您不需要第一个。您可以通过枚举播放器的行来定义序列。然后,对于每个序列,日期和序列之间的差异是常数。然后,额外的排名可以得到你想要的。

定义序列:

select stl.*,
       row_number() over (partition by player_id, groupid order by date) as seqnum
from (select stl.*,
             datediff(day, date,
                      row_number() over (partition by player_id order by date) as groupid
      from steppers_step_log stl
     ) stl

现在,您可以使用以下方式获取“符合条件”的行:

where seqnum > 1

要获得每个玩家的三个最高值,您可以这样做:

with stl as (<above query>)
select *
from (select stl.*,
             row_number() over (partition by player_id order by steps desc) as scorenum
      from stl
      where seqnum > 1
     ) stl
where scorenum <= 3