如何在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