我有一个表格,用于记录已登录我们系统的用户。它会在登录时和注销时记录。我需要生成一些SQL,它会为我们提供当天的小时数和当时登录的人数列表。我可以这样做一次,但我不知道如何扩展它以产生一天中的每个小时。如果可能,我真的不想做24个SQL语句!?
SELECT COUNT(userID) AS "count of users"
FROM LogonTimes
WHERE (LoginTime > '2011-09-12 09:00:00') AND (LogoffTime < '2011-09-12 10:00:00 ')
上面会产生说“3”。这显示3人在9点到10点之间登录。
任何想法?!
[编辑]这是人们在下面猜到的SQL Server - 抱歉没有指定!我会试试这些建议并尽快回复!谢谢:) [/ edit]
答案 0 :(得分:2)
对于SQL Server,你可以做...
declare @DayToCheck datetime
set @DayToCheck = '2011-09-12'
;with C as
(
select @DayToCheck as H
union all
select dateadd(hour, 1, H)
from C
where dateadd(hour, 1, H) < dateadd(day, 1, @DayToCheck)
)
select C.H as [hour],
count(L.userID) as [count of users]
from C
left outer join LogonTimes as L
on L.LogoffTime > C.H and
L.LoginTime < dateadd(hour, 1, C.H)
group by C.H
在此尝试:http://data.stackexchange.com/stackoverflow/q/112462/
SQL Server 2000的一个版本,如果是CTE,则使用数字表。这里我使用master..spt_values。
declare @DayToCheck datetime
set @DayToCheck = '2011-09-12'
select dateadd(hour, N.number, @DayToCheck) as [hour],
count(L.userID) as [count of users]
from master..spt_values as N
left outer join LogonTimes as L
on L.LogoffTime > dateadd(hour, N.number, @DayToCheck) and
L.LoginTime < dateadd(hour, N.number + 1, @DayToCheck)
where N.Type = 'P' and
N.Number between 0 and 23
group by dateadd(hour, N.number, @DayToCheck)
答案 1 :(得分:0)
将LoginTime列舍入到最近的小时,然后将其分组。
至于Martin的观点,如果您希望在时间范围内有用户登录的总计数,您还需要在where子句中添加一些其他条件,即
在当前小时之前登录并在当前小时内退出
在当前时间内登录并在当前时间之后注销
在当前小时之前登录并在当前小时之后注销
您甚至可能需要考虑未记录的注销日期时间,具体取决于您的注销系统的工作方式。
答案 2 :(得分:0)
目前还不清楚你在使用什么环境(SQL SERVER vs. Oracle vs Other)。以下内容将特定于Oracle:
SELECT
HOUR_OF_DAY,
COUNT(userID) AS "count of users"
FROM LogonTimes,
(
select TRUNC(SYSDATE)+COUNTER/24 AS HOUR_OF_DAY from
(
select
level-1 as COUNTER
from dual
connect by level <=24
) a
where COUNTER >= 0
)
WHERE (LoginTime >= HOUR_OF_DAY) AND (LogoffTime < HOUR_OF_DAY+1/24)
注意:这与您的原始版本一样,计算在一小时内登录的人员,不一定每个人都登录(即他们已经登录,并且保持登录状态几个小时)。
编辑:如果你想捕捉在一小时内任何时候登录的所有人,WHERE子句应该是:
WHERE (LoginTime < HOUR_OF_DAY+1/24) -- logged in before end of the hour
AND (LogoffTime > HOUR_OF_DAY) --logged off after start of the hour
答案 3 :(得分:0)
由于您没有指定SQL语言,我将使用SQL Server。我正在使用表值函数,但你可以使用临时表来做同样的事情。所需的功能是:
CREATE FUNCTION [dbo].[NumbersBetween] (
@start int,
@end int
) RETURNS @ret TABLE (Num int) AS BEGIN
DECLARE @x int
SET @x = @start
WHILE (@x <= @end) BEGIN
INSERT INTO @ret VALUES(@x)
SET @x = @x + 1
END
RETURN
END
GO
用于测试的表格是:
CREATE TABLE LogonTimes(
SessionId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
LoginTime datetime NOT NULL,
LogOffTime datetime NULL
)
INSERT INTO LogonTimes(LoginTime, LogOffTime) VALUES('2011-09-12 09:10', '2011-09-12 10:10')
最后,获取所需信息的功能(假设您每天都需要这些信息,而不仅仅是所有日期)
DECLARE @queryDate datetime
SET @queryDate = '2011-09-12'
SELECT DATEADD(hour, hours.Num, @queryDate) AS HourOfDay, COUNT(LogonTimes.SessionId) AS SessionCount
FROM dbo.NumbersBetween(0, 23) hours
LEFT JOIN LogonTimes
ON LogonTimes.LoginTime < DATEADD(hour, hours.Num + 1, @queryDate)
AND ISNULL(LogonTimes.LogOffTime, GETDATE()) > DATEADD(hour, hours.Num, @queryDate)
GROUP BY hours.Num
ORDER BY HourOfDay
这会产生以下结果(截断以删除开头和结尾的空白)
HourOfDay SessionCount
----------------------- ------------
....
2011-09-12 07:00:00.000 0
2011-09-12 08:00:00.000 0
2011-09-12 09:00:00.000 1
2011-09-12 10:00:00.000 1
2011-09-12 11:00:00.000 0
....
此解决方案会考虑仍在登录的用户,在同一小时内登录和注销的用户以及在午夜过后留下的用户。
-
更新了解决方案,仅考虑查询一天,删除了SQL2008依赖项。