2015-11-07 1 views
0

мне нужен запрос в MSSQL, чтобы вернуться к следующему результату:Возврат отчетливую дату последнего входа из следующей таблицы

ID клиента, UserName, EVENTDATE

отчетливо для каждого ClientID на основе наиболее позднюю дату из В следующей таблице:

Login History table

например: С учетом приведенной выше таблице, возвращение:

450SB 2013-03-01 16:40:29 nevadan 
    LASB 2013-03 001 16:37:27 siteuser 

и т.д.

Думал о создании курсора для: SELECT DISTINCT ClientId из ТАБЛИЦЫ и пробегаем по каждой возвращающейся только ввод MaxDate, но не думаю, что это было очень эффективным.

ответ

0

Вы можете использовать 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 

EDIT

Учитывая у вас есть первичный ключ и вторая таблица с именем клиента, рассмотрят сценарии ниже:

;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 
+0

Это хау первичный: Идентификатор истории - Спасибо. –

+0

Если HistoryID является постоянно увеличивающимся полем идентификации, вы можете использовать MAX (HistoryID) вместо MAX (EventDate). Это может ускорить соединение немного. –

+0

Спасибо, сэр. Если бы я хотел вернуть в запрос более явное имя для clientId, которое находится в таблицеB как поле sccCompanyName на tableb.sccClientID = table.clientId. Как мне изменить ваш запрос? –

0

У меня нет MSSQL, установленного на моем компьютере, поэтому я не могу проверить это для вас, но, как вариант, я могу добавить фильтр ORDERBY ASC eventdate на ваш SQL, а затем выбрать только первую строку для достижения вашей Цель.

Так что это будет что-то вроде

SELECT DISTINCT ClientId ИЗ ТАБЛИЦЫ ORDER BY EVENTDATE

Что касается ли это более эффективно или нет ... Я думаю, что вы Willl должны смотреть на запрос план выполнения, чтобы увидеть, какие операции выполняются MSSQL для выполнения запроса, производительность, вероятно, не такая хорошая, как предыдущая, потому что этот SQL делает что-то дополнительное, то есть сортирует.

При таком подходе по крайней мере, вы не должны думать о эффективный алгоритм сортировки себя, и это экономит время на обдумывание алгоритма и пару строк кода: P

+0

Msg 145, Level 15, State 1, Lin e 1 Элементы ORDER BY должны быть указаны в списке выбора, если указан параметр SELECT DISTINCT. –

+0

Ooops, у меня нет большого опыта работы с MSSQL, но вы можете попробовать использовать GROUP BY вместо DISTINCT? так что-то вроде этого; Выберите ClientID, UserName, EventDate из группы групп по ClientId Order by eventdate asc –

0

То, что вы описываете, это немного сложнее чем можно было бы подумать, главным образом потому, что вам нужно имя пользователя в дополнение к 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 

... примечание: если вы избавитесь от UserName это просто:

SELECT 
    ClientId 
    MaxEventDate = MAX(EventDate) 
FROM 
    SomeTable 
GROUP BY 
    ClientId 
Смежные вопросы