从下表返回不同的上次登录日期

时间:2015-11-07 01:10:45

标签: sql-server sql-server-2008

我需要在MSSQL中查询以返回以下结果:

客户ID,用户名,EventDate

根据下表中的最新日期明确表示每个ClientID:

Login History table

例如:根据上表,返回:

argv[3]

正考虑为TABLE创建一个游标:SELECT DISTINCT来自TABLE的ClientId 并循环遍历每个只返回maxdate的条目,但没有想到它 很有效率。

3 个答案:

答案 0 :(得分:0)

我的计算机上没有安装MSSQL,所以我无法为您测试这个,但我认为您可以在SQL中添加“ORDERBY ASC eventdate”过滤器,然后只选择第一行来实现您的目标

所以它会像

SELECT DISTINCT ClientId   FROM TABLE  ORDER BY eventdate

关于这是否更有效......我认为你将不得不查看查询执行计划,看看MSSQL做了什么操作来进行查询,性能可能不如以前那么好一,因为这个SQL正在做一些额外的事情,即排序。

通过这种方法,至少你不必自己考虑有效的排序算法,它可以节省你对算法的思考和耦合代码行的时间:P

答案 1 :(得分:0)

您所描述的内容比人们想象的要复杂得多,主要是因为除了ClientID和EventDate之外还需要UserName。

这应该可行,虽然我没有在本地构建你的架构来测试,所以如果你有任何错误,请告诉我。

SELECT
    t1.*
FROM
    SomeTable t1
INNER JOIN
    (
    SELECT
        ClientId
        MaxEventDate = MAX(EventDate)
    FROM
        SomeTable
    GROUP BY
        ClientId
    ) t2
ON
    t1.ClientID = t2.ClientID
    AND t1.EventDate = t2.EventDate

...注意:如果你摆脱了UserName,它只是:

SELECT
    ClientId
    MaxEventDate = MAX(EventDate)
FROM
    SomeTable
GROUP BY
    ClientId

答案 2 :(得分:0)

您可以使用CTE获取每个客户端的最新访问日期,然后在CTE上重新加入以获取每个客户端的每个最新访问日期的用户名。如果你的表有主键,那么JOIN在性能,可读性和优雅方面会更好。

;WITH   latestClientAccess (ClientId, LatestEventDate) AS (
        SELECT  ClientId, MAX(EventDate)
        FROM    MyTable
        GROUP   BY ClientId
)
SELECT  t.ClientId, t.UserName, lca.LatestEventDate [EventDate]
FROM    MyTable t
INNER   JOIN latestClientAccess lca
        ON  t.ClientId=lca.ClientId
            AND  t.EventDate=lca.LatestEventDate

可以通过运行下面的脚本来执行上述概念和脚本的快速本地测试。这样,任何查看此响应的人都可以在不必创建任何模式的情况下进行测试。

declare @temp table(ClientId int, EventDate datetime, UserName varchar(20)) 

insert  into @temp
select  1, '2015-11-06 00:00:00', 'user1'

insert  into @temp
select  2, '2015-11-06 00:01:00', 'user1'

insert  into @temp
select  1, '2015-11-06 00:01:00', 'user2'

insert  into @temp
select  1, '2015-11-06 00:03:00', 'user1'

;WITH   latestClientAccess (ClientId, LatestEventDate) AS (
        SELECT  ClientId, MAX(EventDate)
        FROM    @temp
        GROUP   BY ClientId
)
SELECT  t.ClientId, t.UserName, lca.LatestEventDate [EventDate]
FROM    @temp t
INNER   JOIN latestClientAccess lca
        ON  t.ClientId=lca.ClientId
            AND  t.EventDate=lca.LatestEventDate

修改

考虑到您确实拥有主键和具有客户端名称的第二个表,请考虑以下脚本:

;WITH   latestClientAccess (ClientId, HistoryId) AS (
        SELECT  ClientId, MAX(HistoryId)
        FROM    MyTable
        GROUP   BY ClientId
)
SELECT  ct.ClientName, t.UserName, t.EventDate
FROM    MyTable t
INNER   JOIN latestClientAccess lca
        ON  t.HistoryId=lca.HistoryId
INNER   JOIN MyClientTable ct
        ON  t.ClientId=ct.ClientId

用于快速测试最新事件概念(无客户名称):

declare @temp table(HistoryId int, ClientId int, EventDate datetime, UserName varchar(20)) 

insert  into @temp
select  1, 1, '2015-11-06 00:00:00', 'user1'

insert  into @temp
select  2, 2, '2015-11-06 00:01:00', 'user1'

insert  into @temp
select  3, 1, '2015-11-06 00:01:00', 'user2'

insert  into @temp
select  4, 1, '2015-11-06 00:03:00', 'user1'

;WITH   latestClientAccess (ClientId, HistoryId) AS (
        SELECT  ClientId, MAX(HistoryId)
        FROM    @temp
        GROUP   BY ClientId
)
SELECT  t.ClientId, t.UserName, t.EventDate
FROM    @temp t
INNER   JOIN latestClientAccess lca
        ON  t.HistoryId=lca.HistoryId