SQL查询查找一个月中每天的第一个和最后一个记录之间的小时差异,并将每个差异相加以查找总计

时间:2015-12-04 13:08:49

标签: sql sql-server

这不是用一句话描述的最简单的查询,这就是为什么标题可能不是最好的。

基本上我有登录日志。此日志如下所示:

ContactId, LocationId, TimeStamp

这些代表在指定时间在某个地点看到的联系人(注册人)。

我想要做的就是选择一个日期时间窗口,对于该窗口中的每一天,我想进行第一次登录,然后进行最后一次登录并计算出小时数差异。这种小时差异应该会影响总体总数,估算联系人在该月份在该地点所花费的总时间。

显然可以忽略联系人未被看到的日子,并且不应该使用只有一次联系人的日子,因为无法计算差异。

我知道如何找出两个小时之间的差异:

select DATEDIFF(HOUR, datetime1, datetime2) as hoursestimate

但我不确定如何:

  1. 将datetime1和datetime2设为一天的第一个和最后一个记录。
  2. 循环浏览数据,增加当天的点数,以查找当月的累计小时数(TotalHours)。
  3. 根据第一个和最后一个看到的差异,我会在整个时间段内累计累计小时数,我将使用我的联系表执行联接以通过此TotalHours列获取他们的姓名和顺序,所以希望最终表我希望从查询返回的内容如下:

    Id    FirstName     LastName     TotalHours
    35     Bob          Bobberson    65
    40     Jim          Jimmerson    63
    2      Harry        Harrison     54
    

    我已经失去了第1步和第2步。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我想你想要两个聚合:

select contactid, sum(hoursestimate) as total
from (select contactid, cast(TimeStamp as date) as dte,
             DATEDIFF(HOUR, min(TimeStamp), max(TimeStamp)) as hoursestimate
      from t
      where TimeStamp >= @start and TimeStamp < @end
      group by contactid, cast(TimeStamp as date)
     ) t
group by contactid;

答案 1 :(得分:1)

有几种不同的技术可以帮助你。

CAST将允许您相互删除日期时间戳的日期和时间部分。这对于从同一天,但不同时间一起分组多个记录非常方便。

HAVING可用于过滤掉一天只有记录的联系人。这可以通过计算贡献记录的数量,并删除低于阈值的记录。

这个例子结合了这些技术:

Exmaple

WITH SampleDate AS
    (
        /* Lets make some records to experiment with.
         */
        SELECT
            r.*
        FROM
            (
                VALUES
                    (1, 1, '2015-01-01 09:00:00.000'),
                    (1, 1, '2015-01-01 12:00:00.000'),
                    (1, 1, '2015-01-01 17:00:00.000'),
                    (2, 1, '2015-01-01 09:00:00.000')
            ) AS r(ContactId, LocationId, [TimeStamp])
    )
SELECT
    ContactId, 
    LocationId,
    CAST([TimeStamp] AS DATE)                AS [Day],    
    MIN(CAST([TimeStamp] AS TIME))            AS FirstSeenTime,
    MAX(CAST([TimeStamp] AS TIME))            AS LastSeenTime,    
    DATEDIFF(
        HOUR,
        MIN(CAST([TimeStamp] AS TIME)),
        MAX(CAST([TimeStamp] AS TIME))
    )                                        AS HoursEstimate
FROM
    SampleDate
GROUP BY
    ContactId, 
    LocationId,
    CAST([TimeStamp] AS DATE)        -- Removing the time allows us to create 1 record per day.
HAVING
    COUNT(*) > 1                    -- Make sure we've seen the contact at least twice.
;