如何在SQL中获取每个组的最后一条logging

我正面临一个相当有趣的问题。 我有一个表结构如下:

CREATE TABLE [dbo].[Event] ( Id int IDENTITY(1,1) NOT NULL, ApplicationId nvarchar(32) NOT NULL, Name nvarchar(128) NOT NULL, Description nvarchar(256) NULL, Date nvarchar(16) NOT NULL, Time nvarchar(16) NOT NULL, EventType nvarchar(16) NOT NULL, CONSTRAINT Event_PK PRIMARY KEY CLUSTERED ( Id ) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ) 

所以问题是我必须在网格中显示这些数据。 有两个要求。 第一个是显示所有事件,而不pipe应用程序抛出它们。 这很简单 – select语句将很容易地完成这项工作。

第二个要求是能够按Application对事件进行分组。 换句话说,以一种方式显示所有事件,如果ApplicationId被重复多次,只抓取每个应用程序的最后一个条目。 此查询/视图中不再需要事件(Id)的主键。

您还可能注意到事件date和时间是string格式。 这是可以的,因为它们遵循标准的date时间格式:mm / dd / yyyy和hh:mm:ss。 我可以这样拉:

 Convert( DateTime, (Date + ' ' + Time)) AS 'TimeStamp' 

我的问题是,如果我在其余的列使用AGGREGATE函数,我不知道他们将如何performance:

 SELECT ApplicationId, MAX(Name), MAX(Description), MAX( CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp', MAX( EventType ) FROM Event GROUP BY ApplicationId 

我犹豫不决的原因是因为像MAX这样的函数会从(子)logging集中返回给定列的MAX 。 没有必要拉最后的纪录!

关于如何select每个应用程序的最后一个logging的任何想法?

您可以使用排名function和公用表格expression式 。

 WITH e AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY ApplicationId ORDER BY CONVERT(datetime, [Date], 101) DESC, [Time] DESC ) AS Recency FROM [Event] ) SELECT * FROM e WHERE Recency = 1 

由于SQL Server 2012可以简单地

 SELECT [Month] , [First] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month]) , [Last] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month] DESC) FROM [dbo].[Table] GROUP BY [Month] ORDER BY [Month] 
 SELECT E.ApplicationId, E.Name, E.Description, CONVERT(DateTime, (E.Date + ' ' + E.Time)) AS 'TimeStamp', E.EventType FROM Event E JOIN (SELECT ApplicationId, MAX(CONVERT(DateTime, (Date + ' ' + Time))) AS max_date FROM Event GROUP BY ApplicationId) EM on EM.ApplicationId = E.ApplicationId and EM.max_date = CONVERT(DateTime, (E.Date + ' ' + E.Time))) 

你可以使用一个子查询或CTE表来做到这一点:

 ;WITH CTE_LatestEvents as ( SELECT ApplicationId, MAX( CONVERT(DateTime, (Date + ' ' + Time))) AS 'LatestTimeStamp', FROM Event GROUP BY ApplicationId ) SELECT ApplicationId, Name, Description, CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp', EventType FROM Event e Join CTE_LatestEvents le on e.applicationid = le.applicationid and CONVERT(DateTime, (e.Date + ' ' + e.Time))) = le.LatestTimeStamp 

因为在那里没有where子句,logging的子集就是所有的logging。 但是,你正在把我认为错误的列放在最大。 这个查询会给你你要找的。

 Select max(applicationid), name, description, CONVERT(DateTime, (Date + ' ' + Time)) from event group by name, description, CONVERT(DateTime, (Date + ' ' + Time)) 

你可以使用一个子查询group by – group by参数不需要在select中。 这是假定Id是一个自动递增的,所以最大的是最近的。

 SELECT ApplicationId, Name, Description, CONVERT(DateTime, (Date + ' ' + Time)) AS 'TimeStamp', EventType FROM Event e WHERE Id in (select max(Id) from Event GROUP BY ApplicationId) 

我认为它会为那些愿意取得最后插入的logging的人工作,它应该被分组:

select * from(select * from TableName ORDER BY id DESC)AS x GROUP BY FieldName

它将为以下工作:

表结构 ID名称状态1 Junaid是2 Jawad否3 Fahad是4 Junaid否5 Kashif是

查询之后的结果以上 ID名称状态4 Junaid No 2 Jawad No 3 Fahad是4 Kashif是

这只不过是由名字组成的最后一个logging。

经过6年的SQL Server的另一个答案:

 select t1.[Id], t2.[Value] from [dbo].[Table] t1 outer apply ( select top 1 [Value] from [dbo].[Table] t2 where t2.[Month]=t1.[Month] order by [dbo].[Date] desc ) 

尽pipe我喜欢Postgresql解决scheme,但是它的独特function更好,而且效率更高:

 select distinct on (id),val from tbl order by id,val