Как получить последнюю запись в группе в SQL
я столкнулся с довольно интересной проблемой. У меня есть таблица со следующей структурой:
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
)
)
Итак, проблема в том, что я должен отображать эти данные в сетке. Есть два требования. Первый-отобразить все события, независимо от того, какое приложение их кинул. Это просто-оператор select сделает эту работу очень легко.
второе требование-уметь группировать события по Application
. Другими словами отображать все события таким образом, что если ApplicationId
повторяется более одного раза, захватить только последнюю запись для каждого приложения. Первичный ключ события (Id) на данный момент больше не нужен в этом запросе/представлении.
вы также можете заметить, что дата и время события находятся в строковом формате. Это нормально, потому что они следуют стандартным форматам даты: mm/dd/yyyy и hh:mm:ss. Я могу вытащить их следующим образом:
Convert( DateTime, (Date + ' ' + Time)) AS 'TimeStamp'
моя проблема в том, что если я использую агрегатные функции на остальных столбцах, я не знаю, как будут ли они себя вести:
SELECT
ApplicationId,
MAX(Name),
MAX(Description),
MAX( CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp',
MAX( EventType )
FROM
Event
GROUP BY
ApplicationId
причина, по которой я не решаюсь сделать это, заключается в том, что такая функция, как MAX
возвращает наибольшее значение для данного столбца из (sub)набора записей. Не надо тянуть последнюю запись!
любые идеи о том, как выбрать только последние записи на основе каждого приложения?
8 ответов
вы можете использовать ранжирующая функция и a общее табличное выражение.
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)))
вы можете использовать subqery или КТР стол для этого:
;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, подмножество записей-это все записи. Но вы ставите max на неправильный столбец(ы), я думаю. Этот запрос даст вам то, что вы ищете.
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)
Я думаю, что это будет работать для многих, желающих получить последнюю вставленную запись, и она должна быть group by:
select * from (select * from tableName ORDER by id DESC) AS X GROUP BY FieldName
Он будет работать для следующего:
Структура Таблицы Статус ID имя 1 Junaid Да 2 Jawad No 3 Фахад Да 4 Junaid No 5 Кашиф Да
Результаты После Запроса Выше ID имя Статус 4 Junaid No 2 Jawad No 3 Фахад Да 4 Кашиф Да
это просто результат последней записи группы по именам.
через 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
)
хотя мне нравится решение Postgresql намного лучше с его отличной функцией, которая приятнее для ввода и намного эффективнее:
select distinct on (id),val
from tbl
order by id,val