Sql 在某一地区消夏

Sql 在某一地区消夏,sql,sql-server,Sql,Sql Server,我有大量的技术数据,可以在现场或在路上, 我想总结一下他们在巫婆网站上的经历和经历。 例如: id UpdateTime UserName SiteID 488565 2019-02-18 19:07:24.000 stephen null 488388 2019-02-18 17:34:52.000 stephen 297 488558 2019-02-18 18:06:48.000 stephen 297 4885

我有大量的技术数据,可以在现场或在路上, 我想总结一下他们在巫婆网站上的经历和经历。 例如:

id        UpdateTime            UserName    SiteID
488565  2019-02-18 19:07:24.000 stephen      null
488388  2019-02-18 17:34:52.000 stephen      297
488558  2019-02-18 18:06:48.000 stephen      297
488565  2019-02-18 18:07:24.000 stephen      297
488565  2019-02-18 14:07:24.000 stephen      null
483170  2019-02-18 13:53:14.000 stephen      299
488565  2019-02-18 11:07:24.000 stephen      null
483170  2019-02-18 10:53:14.000 stephen      297
这一天,该技术在297中出现了两次,我希望每个技术都能得到这个结果(结束时间是我得到Null或different SiteID的时间):

谢谢,
eyal不能发表评论,因为没有声誉:(?!?因此,尽管还有一些问题,我还是会作为答案发布。原则上,您可以将空值站点记录连接到非空站点记录。如果您不能保证空值站点ID表示“退出”,而非空站点ID表示进入,那么就没有“起点”,您需要进行表扫描。如果您可以保证的话(或单独处理例外情况)则查询可以采用以下形式:

select t1.UserName, 
    t1.UpdateTime as EntryTime, 
    t2.UpdateTime as ExitTime, 
    datediff(MI, t1.UpdateTime, t2.UpdateTime) as TimeInSite, 
    t1.SiteId
from TimeTable t1
join TimeTable t2 on t2.id in 
    (select id from TimeTable 
        where 
            -- want the same user
            UserName = t1.UserName
            -- site id null/different means 'exited site'
            and (siteId is null)  
            -- now get the entry with the minium update time that is greater than the entry time
            and UpdateTime = (select min(UpdateTime) from TimeTable where UpdateTime > t1.UpdateTime
        )
    )
where t1.SiteId is not null
order by EntryTime
这并没有考虑到同一次访问可以有多个“非空”站点ID(即三个297)。理想情况下,这应该避免。如果不能,则可以首先将这些条目整理到临时表中,以仅选择第一个条目的时间

上面的查询输出以下内容(SQL server,请注意,为了清晰起见,我添加了进入和退出时间)。由于有多个297,这不是您想要的100%,但可能会让您开始。现在时间不够了,可能其他人可以提供100%的解决方案。祝您好运

UserName     EntryTime               ExitTime                TimeInSite  SiteId
------------ ----------------------- ----------------------- ----------- -----------
stephen      2019-02-18 10:53:14.000 2019-02-18 11:07:24.000 14          297
stephen      2019-02-18 13:53:14.000 2019-02-18 14:07:24.000 14          299
stephen      2019-02-18 18:07:24.000 2019-02-18 19:07:24.000 60          297

无法评论,因为没有声誉:(?!?因此,尽管还有一些问题,我还是会作为答案发布。原则上,您可以将空值站点记录连接到非空站点记录。如果您不能保证空值站点ID表示“退出”,而非空站点ID表示进入,那么就没有“起点”,您需要进行表扫描。如果您可以保证的话(或单独处理例外情况)则查询可以采用以下形式:

select t1.UserName, 
    t1.UpdateTime as EntryTime, 
    t2.UpdateTime as ExitTime, 
    datediff(MI, t1.UpdateTime, t2.UpdateTime) as TimeInSite, 
    t1.SiteId
from TimeTable t1
join TimeTable t2 on t2.id in 
    (select id from TimeTable 
        where 
            -- want the same user
            UserName = t1.UserName
            -- site id null/different means 'exited site'
            and (siteId is null)  
            -- now get the entry with the minium update time that is greater than the entry time
            and UpdateTime = (select min(UpdateTime) from TimeTable where UpdateTime > t1.UpdateTime
        )
    )
where t1.SiteId is not null
order by EntryTime
这并没有考虑到同一次访问可以有多个“非空”站点ID(即三个297)。理想情况下,这应该避免。如果不能,则可以首先将这些条目整理到临时表中,以仅选择第一个条目的时间

上面的查询输出以下内容(SQL server,请注意,为了清晰起见,我添加了进入和退出时间)。由于有多个297,这不是您想要的100%,但可能会让您开始。现在时间不够了,可能其他人可以提供100%的解决方案。祝您好运

UserName     EntryTime               ExitTime                TimeInSite  SiteId
------------ ----------------------- ----------------------- ----------- -----------
stephen      2019-02-18 10:53:14.000 2019-02-18 11:07:24.000 14          297
stephen      2019-02-18 13:53:14.000 2019-02-18 14:07:24.000 14          299
stephen      2019-02-18 18:07:24.000 2019-02-18 19:07:24.000 60          297

您可以使用窗口函数执行此操作。您希望将组分配给行,然后进行聚合。分组是如何定义的

在本例中,您希望在组中包含下一个
NULL
值。因此,适用于您的定义是按相反顺序累积的
NULL
值的数量。即:

select t.*,
       sum(case when siteId is null then 1 else 0 end) over (partition by userName order by updatetime desc) as grp
from t;
然后,您可以聚合以获得您想要的:

select username, min(siteid) as siteid,
       min(updatetime) as incometime,
       datediff(minute, min(updatetime), max(updatetime)) as minutes
from (select t.*,
             sum(case when siteId is null then 1 else 0 end) over (partition by userName order by updatetime desc) as grp
      from t
     ) t;

您可以使用窗口函数执行此操作。您希望将组分配给行,然后进行聚合。分组是如何定义的

在本例中,您希望在组中包含下一个
NULL
值。因此,适用于您的定义是按相反顺序累积的
NULL
值的数量。即:

select t.*,
       sum(case when siteId is null then 1 else 0 end) over (partition by userName order by updatetime desc) as grp
from t;
然后,您可以聚合以获得您想要的:

select username, min(siteid) as siteid,
       min(updatetime) as incometime,
       datediff(minute, min(updatetime), max(updatetime)) as minutes
from (select t.*,
             sum(case when siteId is null then 1 else 0 end) over (partition by userName order by updatetime desc) as grp
      from t
     ) t;

为什么siteID 297有两行?您如何确定结束时间?也许您可以添加您自己的解决方法?我假设当siteID为null时,他们已经离开了以前的站点?另外,请您标记您的DBMS?是的,当它为null时,他们离开了站点,而我的DBMS是MSSQL为什么siteID 297有两行,您如何确定结束时间e?也许您可以添加自己的解决方法?我假设当siteID为null时,他们离开了以前的站点?另外,请您标记您的DBMS?是的,当它为null时,他们离开了站点,我的DBMS为MSsql
无法评论,因为没有信誉:(?!?
这是因为人们应该了解SO是如何工作的,以及问答网站和论坛之间的区别。这就是为什么评论如此有限,它们也可以随时删除。这个答案永远不适合评论。50个代表可以很容易地获得。它让我根据一些假设回答,而不是一个简单的回答先问一些澄清问题。
无法评论,因为没有声誉:(?!?
这是因为人们应该了解SO是如何工作的,以及问答网站和论坛之间的区别。这就是为什么评论如此有限,它们也可以随时删除。这个答案永远不适合评论。50个代表可以很容易地获得。它让我根据一些假设回答,而不是一个简单的回答先问一些澄清问题。