简体   繁体   English

SQL查询:如果给出两个DateTime时间戳,如何确定“在N小时内看到”?

[英]SQL Query: How to determine “Seen during N hour” if given two DateTime time stamps?

I'm writing a statistics based application off a SQLite database. 我正在从SQLite数据库编写基于统计的应用程序。 There is a table which records when users Login and Logout (SessionStart, SessionEnd DateTimes). 有一个表记录用户登录和注销的时间(SessionStart,SessionEnd DateTimes)。

What i'm looking for is a query that can show what hours user have been logged in, in sort of a line graph way- so between the hours of 12:00 and 1:00AM there were 60 users logged in (at any point), between the hours of 1:00 and 2:00AM there were 54 users logged in, etc... 我正在寻找的是一个查询,可以显示哪些用户时间已经登录,在排序线图的12:00和1:00 AM之间的时间way-所以有60个用户登录的(在任何点),在凌晨1点到凌晨2点之间有54位用户登录等...

And I want to be able to run a SUM of this, which is why I can't bring the records into .NET and iterate through them that way. 我希望能够运行这个的SUM,这就是为什么我不能将记录带入.NET并以这种方式迭代它们的原因。

I've come up with a rather primative approach, a subquery for each hour of the day, however this approach has proved to be slow and slow. 我想出了一个相当主要的方法,一天中每小时的子查询,但这种方法已被证明是缓慢而缓慢的。 I need to be able to calculate this for a couple hundred thousand records in a split second.. 我需要能够在一瞬间计算出几十万条记录。

  SELECT
        case
        when (strftime('%s',datetime(date(sessionstart), '+0 hours')) > strftime('%s',sessionstart)
        AND strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionend))
        OR (strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionstart)
        AND strftime('%s',datetime(date(sessionstart), '+1 hours')) < strftime('%s',sessionend))
        OR (strftime('%s',datetime(date(sessionstart), '+0 hours')) < strftime('%s',sessionstart)
        AND strftime('%s',datetime(date(sessionstart), '+1 hours')) > strftime('%s',sessionend))
        then 1 else 0 end as hour_zero,
... hour_one, 
... hour_two, 
........ hour_twentythree
FROM UserSession

I'm wondering what better way to determine if two DateTimes have been seen durring a particular hour (best case scenario, how many times it has crossed an hour if it was logged in multiple days, but not necessary)? 我想知道有什么更好的方法可以确定在特定时间内是否已经看到两个DateTimes(最好的情况是,如果它是在多天内记录的话,它已经过了一个小时多少次,但没有必要)?

The only other idea I had is have a "hour" table specific to this, and just tally up the hours the user has been seen at runtime, but I feel like this is more of a hack than the previous SQL. 我唯一的另一个想法是有一个特定于此的“小时”表,并且只计算了用户在运行时看到的小时数,但我觉得这比以前的SQL更像是一个黑客。

Any help would be greatly appreciated! 任何帮助将不胜感激!

Played around a bit on Sybase (T-SQL dialect) and came up with this query. 在Sybase(T-SQL方言)上玩了一下并提出了这个查询。

SELECT
    StartHour AS Hour, COUNT(*) AS SessionCount
FROM
    (SELECT
        CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00') as StartHour,
        DATEADD(HH, 1, CONVERT(DATETIME, '2001-01-01 ' + Hour + ':00:00')) as EndHour
    FROM
        (SELECT '00' AS Hour UNION ALL SELECT '01' AS Hour UNION ALL
        SELECT '02' AS Hour UNION ALL SELECT '03' AS Hour UNION ALL
        SELECT '04' AS Hour UNION ALL SELECT '05' AS Hour UNION ALL
        SELECT '06' AS Hour UNION ALL SELECT '07' AS Hour UNION ALL
        SELECT '08' AS Hour UNION ALL SELECT '09' AS Hour UNION ALL
        SELECT '10' AS Hour UNION ALL SELECT '11' AS Hour UNION ALL
        SELECT '12' AS Hour UNION ALL SELECT '13' AS Hour UNION ALL
        SELECT '14' AS Hour UNION ALL SELECT '15' AS Hour UNION ALL
        SELECT '16' AS Hour UNION ALL SELECT '17' AS Hour UNION ALL
        SELECT '18' AS Hour UNION ALL SELECT '19' AS Hour UNION ALL
        SELECT '20' AS Hour UNION ALL SELECT '21' AS Hour UNION ALL
        SELECT '22' AS Hour UNION ALL SELECT '23' AS Hour) AS Hours
    ) AS T1,
    UserSession AS T2
WHERE
    -- Logged on during, logged off during
    (T2.SessionStart >= T1.StartHour AND T2.SessionEnd < T1.EndHour)
    -- Logged on before, logged off during
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= StartHour AND T2.SessionEnd < T1.EndHour)
    -- Logged on during, logged off after
    OR (T2.SessionStart >= T1.StartHour AND T2.SessionStart < T1.EndHour AND T2.SessionEnd >= T1.EndHour)
    -- Logged on before, logged off after
    OR (T2.SessionStart < T1.StartHour AND T2.SessionEnd >= T1.EndHour)
GROUP BY
    T1.StartHour
ORDER BY
    T1.StartHour

The input needed is the day to aggregate in YYYY-MM-DD form. 所需的输入是以YYYY-MM-DD形式聚合的日子。 Note that it doesn't return any results for the hours where the count is zero. 请注意,它不会返回计数为零的小时数的任何结果。

I'd go with your "hack" idea, but I don't consider it a hack, really - after the hour's over, the value won't ever change, so why not calculate it once and be done with it? 我会考虑你的“黑客”想法,但我不认为这是一个黑客,真的 - 在一小时结束后,价值不会改变,所以为什么不计算一次并完成它呢? Rollup tables are perfectly valid for this and will yield consistent query times regardless of how many users you've been tracking. 汇总表对此非常有效,无论您跟踪的用户数量多少,都会产生一致的查询时间。

You could calculate these every hour or alternatively, you could increment each hour's counter at login/logout events and avoid a scheduled task. 您可以每小时计算一次,或者您可以在登录/注销事件中递增每小时的计数器,并避免计划任务。

Perhaps you could have another table that, when logout times are recorded, populates records to determine hours when the user was logged in? 也许您可以使用另一个表,在记录注销时间时,填充记录以确定用户登录的小时数?

For example 例如

create table hourlyUseLog (
    userID text not null,
    date float, // julian Day
    hour0 integer default 0,
    hour1 integer default 0,

etc...

    hour23 integer default 0,
);

If you had a structure like this, you could do very fast queries of who was logged in (or how many users were logged in) at any given time/date. 如果你有这样的结构,你可以在任何给定的时间/日期快速查询谁登录(或登录了多少用户)。

SQLite also supports bit fields and bit math, so you could also represent all of the hours in a day in a single integer and flip bits depending on the hours that users were active. SQLite还支持位字段和位数学,因此您还可以使用单个整数表示一天中的所有小时数,并根据用户处于活动状态的小时数来翻转位。 This would allow you to do even faster queries with bit masks and would provide a mechanism to convert hours to julian day (time-portion only) representations and/or use a bit counting routine to calculate hours spent in the system. 这将允许您使用位掩码进行更快速的查询,并提供一种机制,将小时转换为朱利安日(仅限时间部分)表示和/或使用位计数例程来计算系统中花费的小时数。

Also, if you need real-time activity reporting and your system allows you to have a centralized representation of who's logged in, you could fire an hourly batch process that updates the hourlyUseLog records. 此外,如果您需要实时活动报告,并且您的系统允许您集中表示谁登录,您可以启动每小时批处理更新hourlyUseLog记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQL查询基于时间戳计算时间跨度 - SQL query to calculate time spans based upon time stamps 确定DateTime是否在给定的日期范围内 - Determine if DateTime is in a given Date Range 如何合并两列日期和时间,并使用linq将其与给定的DateTime比较 - how to combine two columns Date and Time and compare it with given DateTime using linq 如何检查 DateTime.Now 是否仅在时间部分的两个给定日期时间之间? - How to check if DateTime.Now is between two given DateTimes for time part only? 当两个日期时间戳记时,将日期和时间字段合并为一个 - Combined to date and time fields into one when both datetime stamps 给定本地DateTime和lat / lon,如何确定NodeJ中的时区和偏移量? - Given local DateTime and lat/lon, how to determine a timezone and offset in NodeJs? 比较Msbuild中的DateTime标记 - Comparing DateTime stamps in Msbuild C#的强制性DateTime问题-确定UtcNow是否仅在给定的时间跨度之间 - Obligatory DateTime issues with C# - Determine if UtcNow is between given time span only 评估时间为12小时格式的字符串时如何从convert.datetime()获取24小时结果 - how to get 24 hour time result from convert.datetime() when evaluating a string that has time is 12 hour format 确定时间是否落在指定的小时范围内 - Determine if time falls in designated hour range
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM