DATEDIFF函数小问题

本文介绍了一个使用DATEDIFF函数统计用户回流数据时遇到的问题。在调整时区时未正确处理DATEDIFF函数导致统计结果出现偏差,并给出了正确的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DATEDIFF 函数语法如下DATEDIFF ( datepart , startdate , enddate ),返回指定的 startdate enddate 之间所跨的指定 datepart 边界的计数(带符号的整数)。下面来说说我碰到的这个问题。用户表里user里面有个字段Create_Time记录用户注册日期,Last_Login_Time 记录用户最后登录的时间,要统计注册用户在注册后,按注册日期统计第一天、第二天、第三天......第七天,七天以后登录人数。用来了解注册用户的回流信息。
代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->DECLARE @cmdText VARCHAR(8000);
DECLARE @userIndex INT;
SET @cmdText = '';
SET @userIndex = 0;
WHILE @userIndex <30
BEGIN
    IF (@userIndex != 29)
            SELECT @cmdText = @cmdText +
                 'SELECT CONVERT(VARCHAR(10), Create_Time, 120) AS Create_Time, 
                        DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay
                  FROM ' + '  dbo.user' + CONVERT(VARCHAR,@userIndex) 
                         + '  UNION ALL' + CHAR(10); --换行
    ELSE
            SELECT @cmdText = @cmdText + 
                 'SELECT CONVERT(VARCHAR(10), Create_Time, 120) AS Create_Time, 
                         DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay
                  FROM ' + '  dbo.user' + CONVERT(VARCHAR,@userIndex) ;
    
    SET @userIndex = @userIndex + 1;
END;

SELECT @cmdText = 
        'SELECT U.Create_Time,SUM(RegisterNum) AS RegisterNum,  
                SUM(FirstDay) AS FirstDay, SUM(TwoDay) AS TwoDay, 
                SUM(ThirdDay) AS ThirdDay, SUM(FourDay) AS FourDay, 
                SUM(FiveDay) AS FiveDay,SUM(SixDay) AS SixDay, 
                SUM(SevenDay) AS SevenDay, SUM(Others) AS Others
        FROM (
                SELECT  Create_Time, COUNT(Create_Time) AS RegisterNum,
                    CASE WHEN LoginDay = 0 THEN COUNT(Create_Time) ELSE 0 END AS FirstDay,
                    CASE WHEN LoginDay = 1 THEN COUNT(Create_Time) ELSE 0 END AS TwoDay,
                    CASE WHEN LoginDay = 2 THEN COUNT(Create_Time) ELSE 0 END AS ThirdDay,
                    CASE WHEN LoginDay = 3 THEN COUNT(Create_Time) ELSE 0 END AS FourDay,
                    CASE WHEN LoginDay = 4 THEN COUNT(Create_Time) ELSE 0 END AS FiveDay,
                    CASE WHEN LoginDay = 5 THEN COUNT(Create_Time) ELSE 0 END AS SixDay,
                    CASE WHEN LoginDay = 6 THEN COUNT(Create_Time) ELSE 0 END AS SevenDay,
                    CASE WHEN LoginDay > 6 THEN COUNT(Create_Time) ELSE 0 END AS Others
                FROM
                (

                    SELECT T.Create_Time, T.LoginDay
                    FROM
                    ('
                      + @cmdText + 
                    ') T
                )  TT
                GROUP BY  TT.Create_Time, TT.LoginDay
        ) U
        GROUP BY U.Create_Time
        ORDER BY  U.Create_Time';
--PRINT     @cmdText    
EXEC (@cmdText);

 

本来如果到此为止,问题就完了,但是这个数据库实例所在服务器是美国时间,我们要按中国时间来统计,所以我就把上面其中的一段的脚本做了如下改写

代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> IF (@userIndex != 29)
            SELECT @cmdText = @cmdText +
                 'SELECT CONVERT(VARCHAR(10),  DATEADD(hh, 15,Create_Time), 120) AS Create_Time, 
                        DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay
                  FROM ' + '  dbo.user' + CONVERT(VARCHAR,@userIndex) 
                         + '  UNION ALL' + CHAR(10); --换行
 ELSE
            SELECT @cmdText = @cmdText + 
                 'SELECT CONVERT(VARCHAR(10),  DATEADD(hh, 15,Create_Time), 120) AS Create_Time, 
                         DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay
                  FROM ' + '  dbo.user' + CONVERT(VARCHAR,@userIndex) ;
    
    SET @userIndex = @userIndex + 1;

 

当时大概想了想: DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay 求相隔几天,注册时间和最后登录时间都要相加15个小时,那不是等同于没有相加,为了“效率”,我就用了上面的脚本。

下面问题来了,如图所示(执行时间时间是2007-7-26),怎么2010-7-26的数据在TwoDay列是198,2010-7-25注册的用户第三天还有148个登录,明显错了

 

刚开始还一头雾水,觉得自己的逻辑没有出错,后来仔细检查了并和同事讨论了后,才发现自己在上面 DATEDIFF(D, Create_Time, Last_Login_Time) LoginDay这里犯了错误。本意为了提高效率着想,却犯了

一个错误

SELECT DATEDIFF(D, '2010-7-25 0:30', '2010-7-26 23:59')

--加上15个小时后

SELECT DATEDIFF(D, '2010-7-25 15:30', '2010-7-27 15:59')
 上面查询结果是1 和 2 ,问题就出在这里。所以把脚本改写后,就OK了。如果以后碰到类似问题,一定要注意!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值