Sql server 从下表返回不同的上次登录日期
我需要在MSSQL中进行查询以返回以下结果: 客户端ID、用户名、事件日期 根据下表中的最新日期,为每个客户ID指定: e、 g:根据上表,返回:Sql server 从下表返回不同的上次登录日期,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我需要在MSSQL中进行查询以返回以下结果: 客户端ID、用户名、事件日期 根据下表中的最新日期,为每个客户ID指定: e、 g:根据上表,返回: 450SB 2013-03-01 16:40:29 nevadan LASB 2013-03 001 16:37:27 siteuser 等 正在考虑为:从表中选择不同的ClientId创建一个游标 循环遍历每个只返回maxdate的条目,但没有想到 非常有效。我的计算机上没有安装MSSQL,因此我无法为您进行测试,但我认为您可以将ORD
450SB 2013-03-01 16:40:29 nevadan
LASB 2013-03 001 16:37:27 siteuser
等
正在考虑为:从表中选择不同的ClientId创建一个游标
循环遍历每个只返回maxdate的条目,但没有想到
非常有效。我的计算机上没有安装MSSQL,因此我无法为您进行测试,但我认为您可以将ORDERBY ASC eventdate筛选器添加到SQL中,然后只选择第一行以实现目标 所以会是这样的 选择不同的ClientId 从桌子上 按事件日期订购 至于这是否更有效。。。我认为您必须查看查询执行计划,以查看MSSQL执行查询时所执行的操作,从性能角度看,可能不如前一个好,因为此SQL正在执行一些额外的操作,即排序
使用这种方法,至少您不必自己考虑高效的排序算法,而且它可以节省您思考算法和几行代码的时间:p您所描述的内容比人们想象的要复杂一些,主要是因为除了ClientID和EventDate之外,您还需要用户名 这应该是可行的,尽管我没有在本地构建您的模式进行测试,所以如果您有任何错误,请告诉我
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
…注意:如果你去掉用户名,它只是:
SELECT
ClientId
MaxEventDate = MAX(EventDate)
FROM
SomeTable
GROUP BY
ClientId
您可以使用CTE获取每个客户机的最新访问日期,然后重新加入CTE以获取每个客户机的每个最新访问日期的用户名。不过,如果表有主键,那么联接在性能、可读性和优雅性方面会更好
;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
如果指定了select DISTINCT,则Msg 145,级别15,状态1,第1行ORDER BY项必须出现在选择列表中。哦,我对MSSQL没有太多经验,但您可以尝试使用GROUP BY而不是DISTINCT?像这样的事情;从表Group By ClientID Order By EventDate ASCI中选择ClientID、UserName、EventDate。它有一个主:历史ID-谢谢。如果HistoryID是一个不断增加的标识字段,则可以使用MAXHistoryID而不是MAXEventDate。这可能会加快加入的速度。谢谢你,先生。如果我想在查询中返回一个更显式的clientId名称,它作为字段sccCompanyName驻留在tableB.sccClientID=table.clientId上的tableB中。我将如何修改您的查询?@IanFalcon-我已使用主键和客户端名称表的示例更新了我的响应。因此,请在原始问题中尽可能多地包含您的问题。这将使我能够提供一个解决方案,而无需进行太多后续编辑。也就是说,如果这符合您的需要,请将其标记为已接受的答案。我向您道歉。第一次,将改进我未来的问题。你能不能帮我加入讨论会来结束这个问题?。非常感谢,先生