2

我有一个表格,其中包含玩家在任何一天所采取的步骤的信息,我想从数据库中获取 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 

这没有考虑到前 3 个步骤中是否有一个日期条目,我的当前形式的查询将返回 10432、10916 和 9837 作为顶部步骤。

我在弄清楚如何执行 WHERE 命令以确保前一天有该 player_id 的条目时遇到了麻烦,并且希望能提供任何帮助以使其正常工作。

4

3 回答 3

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 

日期添加 (Transact-SQL)

于 2012-10-25T15:22:27.760 回答
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 名中有多个条目。这就是你想要的吗?

于 2012-10-25T15:24:35.010 回答
1

有几种方法可以解决这个问题。其他人可能会使用连接/存在类型查询来解决问题。我喜欢另一种方法,它使用排名函数来获取适当的行。

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

要定义序列:

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
于 2012-10-25T15:30:01.733 回答