我怎么能在SQL中这样做?

时间:2013-05-17 16:17:05

标签: sql postgresql

今天,我需要你的帮助。

我有一个统计网站,我从Game Webservices获取数据。 我想实现一个新功能,但我不知道如何。

我想猜猜玩家的连接时间。

我有一个脚本,每小时收集一次数据并将这些数据存储在一个表中。 想象一下,我有一个表:player_id,得分和小时(整数,只是H),以及月份的日期。

然后,例如,如果小时17和18之间的分数不同,那么玩家已经连接到他的账户。

为了简化,假设我有一张桌子,每天从1到31,小时从0到23。

在月底,我需要执行一个查询来计算每小时玩家在这一小时内连接的天数。

Example :

0 => 31     The player has been connected between 23 and 0  : every days
1 => 3      The player has been connected between 0 and 1  : 3 days a month
2 => 5      The player has been connected between 1 and 2  : 5 days a month
3 => 10     The player has been connected between 3 and 4  : 10 days a month
...
23 => 4

我想我可以从第1小时0到第31天23小时按天和小时以及播放器ID排序 并使用CASE执行第一个SELECT:

SELECT 
    table.*,  
   (CASE WHEN ACTUAL_ROW.score!=PREVIOUS_ROW.score THEN 1 ELSE 0) AS active
FROM table

如果玩家已连接,请了解每一行。 那么每小时做一个GROUP BY和SUM是很简单的。 但我不知道如何将前一行与实际比较

您有任何IDEA或提示如何做到这一点? PL / SQL更好吗?

注意:我正在使用PostGreSQL

谢谢

2 个答案:

答案 0 :(得分:3)

您可以使用LAG窗口函数访问表格的上一行。

尝试使用类似

的内容
SELECT player_id, count(CASE WHEN score > prev_score THEN 1 END)
FROM(
SELECT player_id, score, mm, hh, LAG(score) OVER (ORDER BY mm,hh) as prev_score
FROM your_table)
GROUP BY player_id

其他建议 - 存储完整时间戳而不是日期和小时字段。您可以随时通过功能获取时间戳的日期和小时。

手动窗口功能:onetwo

答案 1 :(得分:0)

这里的问题是我们没有检查播放器“何时连接” 但相反,当玩家“获得积分”时,可能相似 - 或者不相似; 并且每隔一小时(一小时三次登录计为一次)。 同样,一名玩家仍然记录了三个小时并积累了积分 周期将导致在一个,两个或三个数据点中“记录”,具体取决于。

有了这些警告,我们可以自己加入得分表:

SELECT a.player_id, a.day, a.hour, a.score - b.score AS chg
   FROM cdata AS a
   JOIN cdata AS b
   ON (
        (a.player_id = b.player_id AND a.score != b.score)
   AND (
        (a.hour > 0 AND a.day = b.day   AND b.hour = a.hour-1)
        OR
        (a.hour = 0 AND a.day = b.day+1 AND b.hour = 23)
       )
   )

这将为用户提供一系列统计信息,包括他的日期和时间 分数改变了。

您可以在收集subSELECT

中使用它
SELECT player_id, hour, COUNT(player_id) FROM ( ... ) AS changes
    GROUP BY player_id, hour
    ORDER BY player_id, hour;

这将在'更改'中返回1到31之间的数字。没有登录的小时数 不计算在内。

我尝试使用此SQLFiddle提供测试用例。 以上不是PostgreSQL特定的,您可以使用PostgreSQL window functions优化内部查询。