TSQL — как получить МАКСИМАЛЬНОЕ количество нескольких столбцов

#sql-server #tsql #max #multiple-columns

#sql-сервер #tsql #макс #несколько столбцов

Вопрос:

У меня есть таблица с

 EMPLOYEE_CODE, 
ENTITLEMENT_CODE, 
TRANS_DATE, 
UNIQUE_ID, 
HOURS. 
 

Мне нужно получить ЧАСЫ для максимума TRANS_DATE для каждой комбинации EMPLOYEE_CODE , ENTITLEMENT_CODE но возможно, что будет несколько случаев максимального TRANS_DATE, поэтому мне нужно дополнительно уточнить запрос, чтобы получить максимум UNIQUE_ID и, следовательно, ЧАСЫ для этой конкретной строки, которая вернулась. Я пробовал разные методы, но я могу получить часть запроса, но не все вместе.

Так что у меня может быть что-то вроде:

 EMPLOYEE_CODE,  ENTITLEMENT_CODE,   TRANS_DATE, UNIQUE_ID,  HOURS.
-----------------------------------------------------------------
2305            ANNL                04/15/2014  28547       15.55
2305            ANNL                04/15/2014  28622       16.83
2305            ANNL                04/15/2014  28223       18.62
2305            ANNL                04/08/2014  28111       12.22
2305            SICK                04/12/2014  28150       14.47
2305            SICK                04/12/2014  28162       12.44
2305            SICK                03/11/2014  28062       18.66 
 

Так что это должно было бы вернуть

 16.83 for 2305 ANNL 
12.44 for 2305 SICK
 

Любая помощь очень ценится.

Ответ №1:

Попробуйте это:

 ;WITH CTE
AS
(
    SELECT
      *,
      ROW_NUMBER() OVER (PARTITION BY EMPLOYEE_CODE, ENTITLEMENT_CODE
                         ORDER BY TRANS_DATE DESC, UNIQUE_ID DESC) rn
    FROM tbl
)
SELECT 
  EMPLOYEE_CODE, 
  ENTITLEMENT_CODE, 
  HOURS
FROM CTE
WHERE rn = 1
 

ДЕМОНСТРАЦИЯ SQL FIFFLE

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

1. Это хорошо сработало, Гамлет. Я раньше не использовал CTE, поэтому я изучу его немного подробнее, чтобы улучшить свое понимание, но запрос вернул то, что я ожидал. Ваша помощь приветствуется.

Ответ №2:

Попробуйте использовать row_number() с partition by clause

 select * from
(
select *,rn=row_number()over(partition by ENTITLEMENT_CODE order by UNIQUE_ID desc)
from table
)x
where x.rn=1
 

Ответ №3:

Если вы предпочитаете использовать коррелированный подзапрос:

 SELECT HOURS, EMPLOYEE_CODE, ENTITLEMENT_CODE
FROM mytable T1
WHERE NOT EXISTS
(
    SELECT *
    FROM mytable T2
    WHERE  T2.EMPLOYEE_CODE    = T1.EMPLOYEE_CODE
      AND  T2.ENTITLEMENT_CODE = T1.ENTITLEMENT_CODE
      AND (T2.TRANS_DATE > T1.TRANS_DATE
        OR T2.TRANS_DATE = T1.TRANS_DATE AND T2.UNIQUE_ID > T1.UNIQUE_ID)
)
 

Желательно, чтобы у вас был индекс поверх EMPLOYEE_CODE и ENTITLEMENT_CODE (составной), чтобы это работало эффективно.

Ответ №4:

Может быть что-то вроде этого

  Select T.* From Table1 T JOIN
   ( Select Max(S.UNIQUE_ID) MaxUniq,S.EMPLOYEE_CODE,S.ENTITLEMENT_CODE
     From Table1 S Join
        ( Select T1.EMPLOYEE_CODE,T1.ENTITLEMENT_CODE,Max(T1.TRANS_DATE) As MaxDate
          From Table1 T1 Group By T1.EMPLOYEE_CODE,T1.ENTITLEMENT_CODE
        ) JR On S.TRANS_DATE = JR.MaxDate AND S.EMPLOYEE_CODE = JR.EMPLOYEE_CODE AND S.ENTITLEMENT_CODE = JR.ENTITLEMENT_CODE
         Group By S.EMPLOYEE_CODE,S.ENTITLEMENT_CODE
 )R ON T.UNIQUE_ID = R.MaxUniq 
 

Демонстрация скрипки

Вывод будет:


 EMPLOYEE_CODE   ENTITLEMENT_CODE    TRANS_DATE  UNIQUE_ID   HOURS
2305            ANNL                2014-04-15  28622       16.83
2305            SICK                2014-04-12  28162       12.44
 

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

1. Это хорошо сработало, Виньеш, и вернуло то, что я ожидал. Я не уверен, имеет ли это преимущества по сравнению с опубликованным решением CTE. Ваша помощь приветствуется.