Извлечь строку, которая имеет значение Max для столбца - PullRequest
538 голосов
/ 23 сентября 2008

Таблица:

UserId, Value, Date.

Я хочу получить UserId, значение для max (Date) для каждого UserId. То есть значение для каждого идентификатора пользователя, который имеет самую последнюю дату. Есть ли способ сделать это просто в SQL? (Желательно Oracle)

Обновление: Извинения за любую двусмысленность: мне нужно получить ВСЕ UserIds. Но для каждого UserId только та строка, в которой у этого пользователя самая последняя дата.

Ответы [ 34 ]

4 голосов
/ 31 октября 2017

Используйте ROW_NUMBER(), чтобы присвоить уникальный рейтинг по убыванию Date для каждого UserId, затем отфильтруйте первую строку для каждого UserId (т. Е. ROW_NUMBER = 1).

SELECT UserId, Value, Date
FROM (SELECT UserId, Value, Date,
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) rn
      FROM users) u
WHERE rn = 1;
3 голосов
/ 23 ноября 2011
select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))
3 голосов
/ 29 июня 2010

Просто нужно было написать «живой» пример на работе:)

Этот поддерживает несколько значений для идентификатора пользователя на одинаковую дату.

Колонки: Идентификатор пользователя, значение, дата

SELECT
   DISTINCT UserId,
   MAX(Date) OVER (PARTITION BY UserId ORDER BY Date DESC),
   MAX(Values) OVER (PARTITION BY UserId ORDER BY Date DESC)
FROM
(
   SELECT UserId, Date, SUM(Value) As Values
   FROM <<table_name>>
   GROUP BY UserId, Date
)

Вы можете использовать FIRST_VALUE вместо MAX и посмотреть его в плане объяснения. У меня не было времени поиграть с ним.

Конечно, при поиске в огромных таблицах, вероятно, лучше использовать в запросе ПОЛНЫЕ подсказки.

3 голосов
/ 23 сентября 2008
Select  
   UserID,  
   Value,  
   Date  
From  
   Table,  
   (  
      Select  
          UserID,  
          Max(Date) as MDate  
      From  
          Table  
      Group by  
          UserID  
    ) as subQuery  
Where  
   Table.UserID = subQuery.UserID and  
   Table.Date = subQuery.mDate  
2 голосов
/ 23 сентября 2008

Я думаю, что-то вроде этого. (Простите за любые синтаксические ошибки; на данный момент я привык использовать HQL!)

РЕДАКТИРОВАТЬ: Также неправильно прочитал вопрос! Исправил запрос ...

SELECT UserId, Value
FROM Users AS user
WHERE Date = (
    SELECT MAX(Date)
    FROM Users AS maxtest
    WHERE maxtest.UserId = user.UserId
)
2 голосов
/ 23 сентября 2008

(T-SQL) Сначала получите всех пользователей и их maxdate. Присоединитесь к таблице, чтобы найти соответствующие значения для пользователей на максимальных значениях.

create table users (userid int , value int , date datetime)
insert into users values (1, 1, '20010101')
insert into users values (1, 2, '20020101')
insert into users values (2, 1, '20010101')
insert into users values (2, 3, '20030101')

select T1.userid, T1.value, T1.date 
    from users T1,
    (select max(date) as maxdate, userid from users group by userid) T2    
    where T1.userid= T2.userid and T1.date = T2.maxdate

Результаты:

userid      value       date                                    
----------- ----------- -------------------------- 
2           3           2003-01-01 00:00:00.000
1           2           2002-01-01 00:00:00.000
2 голосов
/ 28 апреля 2010

Ответ здесь только Oracle. Вот немного более сложный ответ во всех SQL:

Кто имеет лучший общий результат домашней работы (максимальная сумма очков за домашнюю работу)?

SELECT FIRST, LAST, SUM(POINTS) AS TOTAL
FROM STUDENTS S, RESULTS R
WHERE S.SID = R.SID AND R.CAT = 'H'
GROUP BY S.SID, FIRST, LAST
HAVING SUM(POINTS) >= ALL (SELECT SUM (POINTS)
FROM RESULTS
WHERE CAT = 'H'
GROUP BY SID)

И более сложный пример, который требует некоторого объяснения, для которого у меня нет времени atm:

Дайте книгу (ISBN и название), которая наиболее популярна в 2008 году, т.е. чаще всего заимствована в 2008 году.

SELECT X.ISBN, X.title, X.loans
FROM (SELECT Book.ISBN, Book.title, count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title) X
HAVING loans >= ALL (SELECT count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title);

Надеюсь, это поможет (кому угодно) ..:)

С уважением, Гус

2 голосов
/ 23 сентября 2008

я думаю, вы должны сделать этот вариант для предыдущего запроса:

SELECT UserId, Value FROM Users U1 WHERE 
Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)
2 голосов
/ 23 сентября 2008

Предполагая, что Дата уникальна для данного идентификатора пользователя, вот несколько TSQL:

SELECT 
    UserTest.UserID, UserTest.Value
FROM UserTest
INNER JOIN
(
    SELECT UserID, MAX(Date) MaxDate
    FROM UserTest
    GROUP BY UserID
) Dates
ON UserTest.UserID = Dates.UserID
AND UserTest.Date = Dates.MaxDate 
2 голосов
/ 21 июля 2014

Я довольно опоздал на вечеринку, но следующий хак превзойдет как коррелированные подзапросы, так и любую аналитическую функцию, но имеет одно ограничение: значения должны преобразовываться в строки. Так что это работает для дат, чисел и других строк. Код не выглядит хорошо, но профиль исполнения отличный.

select
    userid,
    to_number(substr(max(to_char(date,'yyyymmdd') || to_char(value)), 9)) as value,
    max(date) as date
from 
    users
group by
    userid

Причина, по которой этот код работает так хорошо, заключается в том, что ему нужно только один раз отсканировать таблицу. Он не требует каких-либо индексов и, что самое важное, не нуждается в сортировке таблицы, как это делают большинство аналитических функций. Индексы помогут, хотя, если вам нужно отфильтровать результат для одного идентификатора пользователя.

...