Sql 统计用户登录后发生的事件数

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

我需要统计用户登录应用程序后发生的事件注册

所有事件都在SQL server数据库中的类似以下事件的表中注册

表说明

ClientID:生成事件的客户端工作站

ApplicationID:生成不同应用程序的事件的应用程序 可以使用数据库

Logtime:生成事件的时间eventid:事件类型。 有很多我感兴趣的东西,其中两个:登录, 注册没有注销

事件数据1-4:关于事件ID的不同信息 -对于eventid=login:data3保存连接的用户名 -对于eventid=enrollment:data1保存对已注册人员的引用

嗯,我想要的是这样的东西

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