TSQL: получить последнего пользователя для каждого случая…только одна запись x user

#sql #tsql

#sql #tsql

Вопрос:

СЦЕНАРИЙ:
Представьте таблицу, подобную этой:

 Auto_INC, UserID_FK, CaseID_FK,    Date
   idX      userX      caseX
  

и когда она заполнена, это выглядит так:

    id1,     user4,     case20,   2010/01/12  
   id2,     user1,     case13,   2010/03/20  
   id3,     user2,     case10,   2010/03/22  
   id4,     user1,     case21,   2011/01/10  
   id5,     user2,      case9,   2011/01/11  
   id6,     user3,     case20,   2011/02/01  
   id7,     user1,      case9,   2011/03/25
  

ВОПРОС:
Как мне получить ОДНУ запись ОБРАЩЕНИЯ с назначенным ПОСЛЕДНИМ пользователем??

Таким образом, если был назначен один пользователь, он автоматически переопределит всех предыдущих пользователей в этом случае.

Что-то вроде этого:

    id7,     user1,      case9,   2011/03/25  
   id2,     user1,     case13,   2010/03/20  
   id4,     user1,     case21,   2011/01/10
   id6,     user3,     case20,   2011/02/01    
   id3,     user2,     case10,   2010/03/22  
  

В этом случае пользователю 1 было назначено 3 случая, пользователю 2 — 2 случая, но один был переопределен пользователем 1, у пользователя 3 был 1 случай, и он переопределил User4 … так что Пользователь4 не получает никакого случая .. поэтому он не появится в списке.

ОБРАТИТЕ ВНИМАНИЕ НА ПРЕИМУЩЕСТВА
В идеале мы должны получать в результате .. столько записей, сколько СЛУЧАЕВ в исходной таблице!!!

Ответ №1:

 declare @T table
(
  Auto_INC int identity primary key, 
  UserID_FK int, 
  CaseID_FK int,
  [Date] date
);

insert into @T values
(4, 20, '2010/01/12'),
(1, 13, '2010/03/20'),
(2, 10, '2010/03/22'),
(1, 21, '2010/01/10'),
(2, 9,  '2010/01/11'),
(3, 20, '2010/02/01'),
(1, 9,  '2010/03/25');

with C as
(
  select *,
         row_number() over(partition by CaseID_FK 
                           order by [Date] desc) as rn
  from @T
)
select Auto_INC, UserID_FK, CaseID_FK, [Date]
from C
where rn = 1;
  

Результат:

 Auto_INC    UserID_FK   CaseID_FK   Date
----------- ----------- ----------- ----------
7           1           9           2010-03-25
3           2           10          2010-03-22
2           1           13          2010-03-20
6           3           20          2010-02-01
4           1           21          2010-01-10
  

Комментарии:

1. Мне пришлось отредактировать свой первоначальный пост, потому что было неясно, что мне нужно получить столько записей, сколько есть СЛУЧАЕВ… с помощью этого SQL я получаю столько записей, сколько … Пользователи.

2. Это правильный синтаксис и результат. Вопрос был изменен, поэтому этот результат больше не является правильным

3. Я согласен… этот ответ возвращал правильный результат, но проблема была на моей стороне, где я неправильно сформулировал вопрос.

4. @Filu, обновленный ответ. С вашим измененным требованием все уже не так сложно.

5. Достаточно забавно… правильный ответ — это как предыдущий, так и этот текущий. Потрясающая мощь SQL, но еще более поразительны знания, которые вы имеете с TSQL 🙂

Ответ №2:

Вы можете выполнить подзапрос в той же таблице, чтобы получить последнего пользователя (и дату для этого пользователя).

 SELECT DISTINCT T1.CaseID_FK, (SELECT TOP 1 T2.UserID_FK
        FROM Table AS T2
        WHERE T2.CaseID_FK = T1.CaseID_FK
        ORDER BY T2.Date DESC) AS User,
    (SELECT TOP 1 T2.Date
        FROM Table AS T2
        WHERE T2.CaseID_FK = T1.CaseID_FK
        ORDER BY T2.Date DESC) AS Date,
FROM Table AS T1
  

Редактировать:

Это должно ограничиваться возвратом только количества строк по мере того, как у вас есть случаи.

 SELECT *
FROM
    (SELECT T1.CaseID_FK, MAX(T1.Date) AS Date
    FROM Table AS T1
    GROUP BY CaseID_FK) AS T2 LEFT JOIN
    (SELECT *
    FROM Table AS T3) AS T4 ON T2.CaseID_FK = T4.CaseID_FK AND T2.Date = T4.Date
  

Комментарии:

1. Я обновил начальный пост, потому что он не был очищен. С помощью этого запроса, если в исходной таблице 1000 записей, я получаю результирующий набор из 1000 записей.

Ответ №3:

использовать

 SELECT * FROM TABLE T WHERE
(T.CASEID_FK, T.Auto_INC) IN
(
SELECT A.CASEID_FK, MAX (A.Auto_INC) MI FROM TABLE A
INNER JOIN (SELECT X.CASEID_FK, MAX (X.DATE) MD FROM TABLE X GROUP BY X.CASEID_FK) Y ON A.DATE = Y.MD AND A.CASEID_FK = Y.CASEID_FK
GROUP BY A.CASEID_FK
)