高级SQL日期减法

时间:2010-12-13 16:51:19

标签: mysql date

我正在开发一款跟踪您登录时间的游戏。它可以节省数据库的登记时间以及退房日期。

这是一个游戏,就像捕获旗帜一样,只有我不想要它做的是计算得分在18:00(下午6点)和09:00(9点)之间的时间。这适用于每一天,而不仅仅是一次。

分数以秒为单位显示。很容易说这是办理登机手续和退房时间之间的差异(减去每天18:00-09:00之间的时间)。

有人是高级SQL日期计算的专家,可以帮助我吗?请!

这是我的基本查询,没有时间减法:

SELECT
SUM(TIMESTAMPDIFF(SECOND,sessions.checkin,IFNULL(sessions.checkout,NOW()))) 
AS score
FROM `sessions`
GROUP BY `user_id`

1 个答案:

答案 0 :(得分:1)

它不会很漂亮(如果您要执行此操作,可能需要添加functions以提高查询的可读性)

假设您没有跨越多天的登录信息,则可以执行以下操作

   SELECT
       user_id,
       SUM(
          TIMESTAMPDIFF(SECOND,
             CASE 
                WHEN sessions.checkin < timestamp(date(sessions.checkin), maketime(9,0,0))
                   THEN timestamp(date(sessions.checkin), maketime(9,0,0))
                WHEN sessions.checkin > timestamp(date(sessions.checkin), maketime(18,0,0))
                   THEN timestamp(date(sessions.checkin)+1, maketime(9,0,0))
                ELSE
                   sessions.checkin
             END,
             CASE
                WHEN IFNULL(sessions.checkout, now()) > timestamp(date(IFNULL(sessions.checkout, now())), maketime(18,0,0))
                   THEN timestamp(date(IFNULL(sessions.checkout, now())), maketime(18,0,0))
                WHEN IFNULL(sessions.checkout, now()) < timestamp(date(IFNULL(sessions.checkout, now())), maketime(9,0,0))
                   THEN timestamp(date(IFNULL(sessions.checkout, now()))-1, maketime(18,0,0))
                ELSE
                   IFNULL(sessions.checkout, now())
             END)) AS score
    FROM `sessions`
    GROUP BY `user_id`

如果跨越多天或准确查询的登录可以使用跨越多天的登录,例如第一天18:05的登记和第3天的8:55结帐,则无效一旦它跨越多天的可数时间,计算不会结束 - 对于每天跨越可数次数的记录,您需要从结果中减去不可数秒的数量。如果您需要帮助,请告诉我。

上面的查询应该相对便宜地运行 - 假设你在整个表上运行它,所以它会进行表扫描,事实上有很多重复的计算它看起来很大并不重要。这些计算在内存中发生,没有额外的I / O,并且应该比磁盘I / O快几个数量级(与原始查询的执行时间相比,让我们知道您是否会看到性能下降)。 / p>