Sql 统计用户登录后发生的事件数
我需要统计用户登录应用程序后发生的事件注册 所有事件都在SQL server数据库中的类似以下事件的表中注册 表说明 ClientID:生成事件的客户端工作站 ApplicationID:生成不同应用程序的事件的应用程序 可以使用数据库 Logtime:生成事件的时间eventid:事件类型。 有很多我感兴趣的东西,其中两个:登录, 注册没有注销 事件数据1-4:关于事件ID的不同信息 -对于eventid=login:data3保存连接的用户名 -对于eventid=enrollment:data1保存对已注册人员的引用 嗯,我想要的是这样的东西Sql 统计用户登录后发生的事件数,sql,sql-server,subquery,performance,Sql,Sql Server,Subquery,Performance,我需要统计用户登录应用程序后发生的事件注册 所有事件都在SQL server数据库中的类似以下事件的表中注册 表说明 ClientID:生成事件的客户端工作站 ApplicationID:生成不同应用程序的事件的应用程序 可以使用数据库 Logtime:生成事件的时间eventid:事件类型。 有很多我感兴趣的东西,其中两个:登录, 注册没有注销 事件数据1-4:关于事件ID的不同信息 -对于eventid=login:data3保存连接的用户名 -对于eventid=enrollment:da
Username | Date | Enrollments
-----------------------------
User1 2014-06-01 11
User2 2014-06-01 6
。。。等等
我已经写了一个查询,但是效率非常低,而且不准确,我想改进它
DECLARE @sdate as datetime
SET @sdate = '2014-06-01 00:00:00.000'
SELECT date, username, sum(enrollments) enrollments
FROM (
SELECT CONVERT(varchar(10),e.logtime,120) as date, upper(e.data3 ) username,
(SELECT count(*)
FROM events r2
WHERE r2.clientID = e.clientID
AND r2.stateid = 'login'
AND r2.ApplicationID = 'application1'
AND r2.logtime between e.logtime AND (SELECT top 1 r3.logtime FROM events r3
WHERE r3.logtime > e.logtime
AND r3.stateid = 'enrollment'
AND r3.clientID = e.clientID
AND r3.ApplicationID in 'application1'
ORDER BY logtime asc)
) as enrollments
FROM events e
WHERE e.logtime > @sdate
AND e.stateid = 'enrollment'
AND e.ApplicationID = 'application1'
) data
GROUP BY date, username
如有任何建议,将不胜感激
ClientID | ApplicationID | logtime | eventid | data1 | data3
-----------------------------------------------------------------------------------
c132 application1 2013-01-05 00:20:48.400 login NULL user1
c132 application1 2013-01-05 00:21:50.393 enrollment 30012 NULL
c132 application1 2013-01-05 00:22:57.330 enrollment 30015 NULL
c129 application1 2013-01-05 00:29:49.197 login NULL user2
c129 application1 2013-01-05 00:34:52.993 enrollment 30021 NULL
c129 application1 2013-01-05 00:36:17.723 enrollment 30022 NULL
c129 application1 2013-01-05 00:37:59.623 enrollment 30026 NULL
c129 application1 2013-01-05 00:39:10.770 enrollment 30028 NULL
c129 application1 2013-01-05 00:41:47.170 enrollment 30031 NULL
c132 application1 2013-01-05 00:54:20.890 enrollment 30040 NULL
c129 application1 2013-01-05 00:55:01.530 enrollment 30041 NULL
c129 application1 2013-01-05 00:56:51.877 enrollment 30044 NULL
c129 application1 2013-01-05 00:57:52.420 enrollment 30045 NULL
c129 application1 2013-01-05 01:00:04.630 enrollment 30050 NULL
c129 application1 2013-01-05 01:01:19.583 enrollment 30056 NULL
c129 application1 2013-01-05 01:08:56.073 login NULL user2
c129 application1 2013-01-05 01:09:31.793 enrollment 30073 NULL
c129 application1 2013-01-05 01:12:38.490 enrollment 30081 NULL
c129 application1 2013-01-05 07:29:25.350 login NULL user2
c129 application1 2013-01-05 07:30:38.087 enrollment 30207 NULL
c129 application1 2013-01-05 07:42:18.793 enrollment 30214 NULL
c129 application1 2013-01-05 07:44:36.540 enrollment 30218 NULL
c129 application1 2013-01-05 07:46:10.693 enrollment 30220 NULL
c129 application1 2013-01-05 08:41:46.073 enrollment 30266 NULL
c129 application1 2013-01-05 08:42:44.627 enrollment 30268 NULL
我不知道它是否会表现得更好,但您可以尝试:
select
username
, enrollment_date
, count(1)
from (
select
el_start.data3 as username
, date_format(e_enrl.logtime,'%Y-%m-%d') enrollment_date -- this is MySQL date format function, you'll need to substitute SQL Server date format function
from
events el_start
join events el_end on el_start.logtime<el_end.logtime and el_start.application_id='application1' and el_end.application_id='application1' and el_start.event_id='login' and el_end.event_id='login'
join events e_enrl on el_start.logtime<e_enrl.logtime and el_end.logtime>e_enrl.logtime and e_enrl.application_id='application1' and e_enrl.event_id='enrollment'
left outer join events el_middle el_middle on el_start.logtime<el_middle.logtime and el_end.logtime>el_middle.logtime and el_middle.application_id='application1' and el_middle.event_id='login'
where 1=1
and el_middle.event_id is null
) enrollments
group by username, enrollment_date
数据库规范化规则在您的模式中被无情地破坏了。我尝试了一下,但由于给定的客户端/应用程序可能有任意数量的连续用户/登录,将给定的注册事件与其原始登录事件关联起来是非常困难的,尤其是在没有样本数据的情况下。我知道数据库的设计有多糟糕,但我对此无能为力。我需要处理这个问题。我添加了一个DB外观的示例。谢谢您的帮助,但它不起作用。也许你可以向我解释一下你使用的逻辑,这样我就可以试着去做。很抱歉,它不起作用:如果不在本地设置所有的表,很难检查这些。我们的想法是el_start应该是一次登录的logtime,el_end应该是后续登录的logtime,el_middle应该是两次登录之间的logtime,并且应该为空,也就是说,我们选择的两次登录之间不应该有任何登录,以保证我们获得两次后续登录。e_enrl应该是在el_start和el_end之间发生的所有入口。您可能想快速查看一下内部子查询,该子查询应该包含所有注册以及我尝试执行的前后登录操作:-在同一站点上的“登录”事件之后计算所有注册,直到发生另一个“登录”事件或没有“登录”事件。-或者对于每个“注册”,在同一站点上注册之前查看第一个“登录”。我发布的查询旨在处理第一个案例,但不起作用。明天我将发布另一个查询,它可以工作,但效率太低,无法查看是否有帮助。
select
username
, enrollment_date
, count(1)
from (
select
el_start.data3 as username
, date_format(e_enrl.logtime,'%Y-%m-%d') enrollment_date -- this is MySQL date format function, you'll need to substitute SQL Server date format function
from
events el_start
join events el_end on el_start.logtime<el_end.logtime and el_start.application_id='application1' and el_end.application_id='application1' and el_start.event_id='login' and el_end.event_id='login'
join events e_enrl on el_start.logtime<e_enrl.logtime and el_end.logtime>e_enrl.logtime and e_enrl.application_id='application1' and e_enrl.event_id='enrollment'
left outer join events el_middle el_middle on el_start.logtime<el_middle.logtime and el_end.logtime>el_middle.logtime and el_middle.application_id='application1' and el_middle.event_id='login'
where 1=1
and el_middle.event_id is null
) enrollments
group by username, enrollment_date