Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何检查两个日期时间变量(from和to)是否属于特定范围?_Sql_Sql Server - Fatal编程技术网

Sql 如何检查两个日期时间变量(from和to)是否属于特定范围?

Sql 如何检查两个日期时间变量(from和to)是否属于特定范围?,sql,sql-server,Sql,Sql Server,我有一个表,它在机器中存储用户会话的日志。它有3列,我将使用。time\u from、time\u to和用户名。我想做的是计算那台电脑的高峰使用时间。为此,我将得到每小时使用的总分钟数和用户数。我试图得到会话的持续时间,这些持续时间在特定的时间范围内,如 时间从>0:00到

我有一个表,它在机器中存储用户会话的日志。它有3列,我将使用。time\u from、time\u to和用户名。我想做的是计算那台电脑的高峰使用时间。为此,我将得到每小时使用的总分钟数和用户数。我试图得到会话的持续时间,这些持续时间在特定的时间范围内,如 时间从>0:00到<1:00,但仅适用于少于一小时的会话。 在我的表格中,有长达6小时的课程,这些课程将在夜间进行。 我的基本要求是获得特定日期内每24小时的会话持续时间,但我无法处理长度超过1小时的会话。有没有什么方法可以完全通过使用SQL来实现这一点,或者我必须用另一个程序来处理它


顺便说一句,我正在使用ms sql server。

制作一个间隔表,然后:

SELECT interval
  , count(*) as sessions
  , count(distinct username) as users
  , SUM(DATEDIFF(s, time_to, time_from)) as seconds_used
FROM (
    SELECT user_sessions.username
      , intervals.interval
      , CASE
          WHEN intervals.time_from < user_sessions.time_from
          THEN user_sessions.time_from
          ELSE intervals.time_from
        END as time_from
      , CASE
        CASE
          WHEN user_sessions.time_to < intervals.time_to
          THEN user_sessions.time_to
          ELSE intervals.time_to
        END as time_from
    FROM user_sessions
      JOIN intervals
        ON intervals.time_from < user_sessions.time_to
          AND user_sessions.time_from < intervals.time_to
  )
GROUP BY interval;

请注意,我不使用MS SQL server,因此我将此SQL设置为通用的,并且相当可移植。也许有一种更简洁的方法可以做到这一点。我也没有进行测试,因此可能会有明显的、希望很容易修复的错误。

基本上,我的解决方案需要建立一个日历,列出开始日期时间和结束日期时间之间的所有小时,然后计算每个小时间隔内的分钟数,最后完全按时间间隔计算

Declare @StartDate datetime
Declare @EndDate datetime

Set @StartDate = ...
Set @EndDate = ...

;With Calendar As
    (
    Select 1 As Num, DateAdd(d, DateDiff(d, 0, @StartDate), 0) As [Date]
    Union All
    Select Num + 1, DateAdd(hh, 1, [Date])
    From Calendar
    Where [Date] <= @EndDate
    )
    , Ranges As
    (
    Select C1.Num, C1.Date As StartDate, Coalesce(C2.Date, @EndDate) As EndDate
    From Calendar As C1
        Left Join Calendar As C2
            On C2.[Num] = C1.Num + 1
    )
    , UsageByHour As
    (
    Select U.username, R.Num As RangeNum, DateDiff( mi, R.StartDate, U.time_to ) As UsageMinutes
    From user_sessions As U
        Join Ranges As R
            On U.time_from Between R.StartDate And R.EndDate
                And U.time_to <= R.EndDate
    Union All       
    Select U.username, R.Num, DateDiff( mi, U.time_from, R.EndDate )
    From user_sessions As U
        Join Ranges As R
            On U.time_from Between R.StartDate And R.EndDate
                And U.time_to > R.EndDate
    Union All       
    Select U.username, R.Num, DateDiff( mi, R.StartDate, U.time_to )
    From user_sessions As U
        Join Ranges As R
            On U.time_to Between R.StartDate And R.EndDate
                And U.time_from < R.StartDate
    )
Select U.username, C.StartDate, C.EndDate, Sum( U.UsageMinutes )
From Usage As U
    Join Calendar As C
        On C.Num = U.RangeNum
Group By U.username, C.StartDate, C.EndDate
Option ( MaxRecursion 0 );
...
    , UsageByInterval As
    (
    Select U.username, C.StartDate, C.EndDate, Sum( U.UsageMinutes ) As UsageMinutes
    From Usage As U
        Join Calendar As C
            On C.Num = U.RangeNum
    Group By U.username, C.StartDate, C.EndDate
    )
    , UsageRanking As
    (
    Select U.username, C.StartDate, C.EndDate, UsageMinutes
        , Row_Number() Over( Partition By U.username 
                                            Order By UsageMinutes Desc ) As Rnk
    From UsageByInterval
    )
Select username, StartDate, EndDate, UsageMinutes
From UsageRanking
Where Rnk = 1