열의 최대 값이있는 행을 가져옵니다.


574

표:

UserId, Value, Date.

UserId, 각 UserId의 max (Date)에 대한 값을 가져오고 싶습니다. 즉, 최신 날짜를 가진 각 UserId의 값입니다. SQL로 간단하게 수행 할 수있는 방법이 있습니까? (바람직하게 오라클)

업데이트 : 모든 모호성에 대한 사과 : 모든 UserId를 가져와야합니다. 그러나 각 UserId에 대해 해당 사용자가 최신 날짜를 가진 행만 해당합니다.


21
특정 사용자 ID에 대해 최대 날짜 값을 갖는 여러 행이있는 경우 어떻게합니까?
David Aldridge

테이블의 주요 필드는 무엇입니까?
vamosrafa

에 비해 다음과 같은 몇 가지 솔루션 : sqlfiddle.com/#!4/6d4e81/1
Used_By_Already

1
@DavidAldridge, 그 열은 독특 할 것입니다.
Pacerier

답변:


397

그러면 my_date 열 값이 해당 사용자 ID의 최대 my_date 값과 동일한 모든 행을 검색합니다. 최대 날짜가 여러 행에있는 사용자 ID에 대해 여러 행을 검색 할 수 있습니다.

select userid,
       my_date,
       ...
from
(
select userid,
       my_date,
       ...
       max(my_date) over (partition by userid) max_my_date
from   users
)
where my_date = max_my_date

"분석 기능 락"

편집 : 첫 번째 의견과 관련하여 ...

"분석 쿼리 및 자체 조인을 사용하면 분석 쿼리의 목적이 무효화됩니다."

이 코드에는 자체 조인이 없습니다. 대신 인라인 뷰 결과에 분석 함수가 포함 된 술어가 있습니다 (매우 다른 문제이며 완전히 표준 관행 임).

"Oracle의 기본 창은 파티션의 첫 번째 행에서 현재 행까지입니다."

windowing 절은 order by 절이있는 경우에만 적용 할 수 있습니다. order by 절이 없으면 기본적으로 windowing 절이 적용되지 않으며 명시 적으로 지정할 수 없습니다.

코드가 작동합니다.


38
880 만 개의 행이있는 테이블에 적용 할 때이 쿼리는 다른 투표가 많은 답변에서 쿼리 시간의 절반이 걸렸습니다.
Derek Mahar

4
누구나 MySQL과 동등한 링크를 게시해야합니까?
redolent

2
이 반품이 중복되지 않습니까? 예 : 두 행에 동일한 user_id와 동일한 날짜가있는 경우 (최대가 됨)
jastr

2
@jastr 나는 질문에 인정 된 것을 생각
데이비드 드리지에게

3
대신에 MAX(...) OVER (...)당신은 또한 사용할 수 있습니다 ROW_NUMBER() OVER (...)(상단-N 당 그룹) 또는 RANK() OVER (...)(최대-N 당 그룹).
MT0

441

많은 사람들이 하위 쿼리 또는 다른 공급 업체별 기능을 사용하여이 작업을 수행하는 것을 보았지만 종종 다음과 같은 방식으로 하위 쿼리없이 이러한 종류의 쿼리를 수행합니다. 일반 표준 SQL을 사용하므로 모든 RDBMS 브랜드에서 작동해야합니다.

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;

t1, 동일 UserId하고 더 큰 날짜를 가진 다른 행이없는 곳 에서 행을 가져옵니다 .

(식별자 "Date"는 SQL 예약어이므로 구분 기호에 넣습니다.)

의 경우 t1."Date" = t2."Date"두배가 나타납니다. 일반적으로 테이블에는 auto_inc(seq)키가 있습니다 (예 :) id. 이중화를 피하기 위해 다음을 사용할 수 있습니다.

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") 
         OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;

@ Farhan의 의견 :

자세한 설명은 다음과 같습니다.

외부 조인이 t1와 조인을 시도합니다 t2. 기본적으로 모든 결과 t1가 반환되고 에 일치하는 항목이 있으면t2 반환됩니다. t2의 지정된 행에 일치하는 항목이 없으면 t1쿼리는 여전히의 행을 반환하고 모든 열의 자리 표시 자로 t1사용합니다 . 이것이 외부 조인이 일반적으로 작동하는 방식입니다.NULLt2

이 쿼리의 트릭 t2동일 userid 하고 더 큰 일치해야하는 조인의 일치 조건을 디자인하는 것 date입니다. 행이 존재하면되는 아이디어 t2가 더 큰이 date, 다음의 행 t1이 비교있어 수없는 큰 일 date이에 대한을 userid. 그러나 일치하는 것이 없으면 (즉 , 행 t2보다 큰 행이없는 경우) 행이 주어진 행에 대해 가장 큰 행 임을 알 수 있습니다.datet1t1dateuserid

이러한 경우의 열 (때 일치가 없다) t2됩니다 NULL에 지정된에도 열 조인 조건 -. 그래서 우리가 사용하는 이유는 주어진 WHERE t2.UserId IS NULL행보다 큰 행을 찾을 수없는 경우를 찾고 있기 때문 입니다.dateuserid


7
와우 빌. 이것이 내가 본이 문제에 대한 가장 창의적인 해결책입니다. 상당히 큰 데이터 세트에서도 성능이 뛰어납니다. 이것은 내가 본 다른 솔루션 들이나이 문제를 해결하려는 나의 시도보다 훨씬 뛰어납니다.
Justin Noel

36
880 만 개의 행이있는 테이블에 적용 할 때이 쿼리는 허용되는 응답보다 거의 두 배가 걸렸습니다.
Derek Mahar

16
@Derek : 최적화는 RDBMS의 브랜드와 버전뿐만 아니라 적절한 색인, 데이터 유형 등의 존재 여부에
달려 있습니다

7
MySQL에서 이러한 종류의 쿼리는 실제로 테이블 간의 데카르트 조인 결과를 반복하여 O (n ^ 2) 시간을 발생시키는 것으로 보입니다. 하위 쿼리 방법을 사용하면 쿼리 시간이 2.0 초에서 0.003 초로 단축되었습니다. YMMV.
Jesse

1
날짜가 가장 큰 날짜가 사용자가 지정한 날짜보다 작거나 같은 행과 일치하도록 이것을 조정하는 방법이 있습니까? 예를 들어 사용자가 "23-OCT-2011"날짜를 제공하고 테이블에 "24-OCT-2011", "22-OCT-2011", "20-OCT-2011"에 대한 행이 포함 된 경우 "22-OCT-2011"을 받으십시오. 내 머릿속을 긁고 잠시 동안이 발췌 문장을 읽었습니다.
Cory Kendall

164
SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
  FROM table
  GROUP BY userid

3
많은 행을 가진 테이블을 사용하는 테스트 에서이 솔루션은 허용되는 답변보다 약 두 배가 걸렸습니다.
Derek Mahar

7
테스트, 제발보기
롭 반 Wijk

나는 다른 솔루션보다 훨씬 빠르다 확인
tamersalama

5
문제는 전체 기록을 반환하지 않는 것입니다
Used_By_Already

@ user2067753 아니요, 전체 레코드를 반환하지 않습니다. 여러 열에 동일한 MAX () .. KEEP .. 식을 사용할 수 있으므로 필요한 모든 열을 선택할 수 있습니다. 그러나 많은 수의 열을 원하고 SELECT *를 사용하려는 경우 불편합니다.
Dave Costa

51

정확한 열 이름을 모르지만 다음과 같습니다.

    사용자 ID, 값을 선택하십시오
      사용자 u1에서
     여기서 날짜 = (최대 선택 (날짜)
                     사용자 u2에서
                    여기서 u1.userid = u2.userid)

3
아마 그리 효율적이지 않습니다, 스티브
David Aldridge

7
아마도 Oracle 쿼리 최적화 프로그램을 과소 평가하고있을 것입니다.
Rafał Dowgird

3
전혀. 이것은 거의 확실하게 날짜를 얻기 위해 중첩 루프 조인으로 전체 스캔으로 구현됩니다. 논리 io에 대해 테이블의 행 수의 4 배 순서로 이야기하고 사소한 양의 데이터에 대해서는 두려운 일입니다.
David Aldridge

4
참고로 "비효율적이지만 효과가있다"는 "효과적이지만 효과가 없다"와 같습니다. 우리는 언제 디자인 목표로 효율적으로 포기 했습니까?
David Aldridge

6
데이터 테이블의 길이가 수백만 행이 아닌 경우 가장 쉬운 솔루션이기 때문에 +1입니다. 코드를 수정하는 모든 기술 수준의 여러 개발자가있는 경우 이해하기 어려운 성능의 1 초보다 이해력이 더 중요합니다.
n00b

35

일하고 있지는 않지만 Oracle이 제공 해야하는 것은 아니지만 Oracle은 IN 절에서 여러 열을 일치시킬 수 있다는 것을 기억합니다. 생각.

아마도 이런 식일 것입니다 (열 목록을 괄호로 묶어야하는지 여부를 기억할 수 없습니다).

SELECT * 
FROM MyTable
WHERE (User, Date) IN
  ( SELECT User, MAX(Date) FROM MyTable GROUP BY User)

편집 : 그냥 진짜 시도했습니다.

SQL> create table MyTable (usr char(1), dt date);
SQL> insert into mytable values ('A','01-JAN-2009');
SQL> insert into mytable values ('B','01-JAN-2009');
SQL> insert into mytable values ('A', '31-DEC-2008');
SQL> insert into mytable values ('B', '31-DEC-2008');
SQL> select usr, dt from mytable
  2  where (usr, dt) in 
  3  ( select usr, max(dt) from mytable group by usr)
  4  /

U DT
- ---------
A 01-JAN-09
B 01-JAN-09

다른 곳에서 언급 된 신기한 물건 중 일부가 더 성능이 좋을 수도 있지만 작동합니다.


4
이것은 PostgreSQL에서도 잘 작동합니다. 그리고 나는 그것의 단순성과 일반성을 좋아합니다. 하위 쿼리는 "내 기준이 있습니다"라고 말하고 외부 쿼리는 "내가보고 싶은 세부 사항이 있습니다"라고 말합니다. +1.
j_random_hacker

13

Oracle을 요청했지만 SQL 2005에서는 다음을 사용합니다.


-- Single Value
;WITH ByDate
AS (
SELECT UserId, Value, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) RowNum
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE RowNum = 1

-- Multiple values where dates match
;WITH ByDate
AS (
SELECT UserId, Value, RANK() OVER (PARTITION BY UserId ORDER BY Date DESC) Rnk
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE Rnk = 1

7

나는 그것을 테스트 할 오라클이 없지만 가장 효율적인 솔루션은 분석 쿼리를 사용하는 것입니다. 다음과 같이 보일 것입니다 :

SELECT DISTINCT
    UserId
  , MaxValue
FROM (
    SELECT UserId
      , FIRST (Value) Over (
          PARTITION BY UserId
          ORDER BY Date DESC
        ) MaxValue
    FROM SomeTable
  )

외부 쿼리를 제거하고 내부를 구별 할 수 있다고 생각하지만 확실하지 않습니다. 그 동안 나는 이것이 작동한다는 것을 안다.

분석 쿼리에 대해 배우려면 http://www.orafaq.com/node/55http://www.akadia.com/services/ora_analytic_functions.html을 읽으십시오 . 다음은 간단한 요약입니다.

후드 분석 쿼리에서 전체 데이터 세트를 정렬 한 다음 순차적으로 처리하십시오. 처리 할 때 특정 기준에 따라 데이터 세트를 분할 한 다음 각 행에 대해 일부 창을보고 (기본값은 현재 행에 대한 파티션의 첫 번째 값-기본값은 가장 효율적 임) a를 사용하여 값을 계산할 수 있습니다 분석 함수 수 (목록은 집계 함수와 매우 유사 함)

이 경우 내부 쿼리의 기능은 다음과 같습니다. 전체 데이터 세트는 UserId, Date DESC로 정렬됩니다. 그런 다음 한 번에 처리합니다. 각 행에 대해 UserId 및 해당 UserId에 대해 표시된 첫 번째 날짜를 반환합니다 (날짜가 DESC로 정렬되므로 최대 날짜 임). 이렇게하면 중복 된 행으로 답을 얻을 수 있습니다. 그런 다음 외부 DISTINCT가 중복을 찌그러 뜨립니다.

이것은 특히 분석 쿼리의 화려한 예가 아닙니다. 훨씬 더 큰 승리를 거두려면 재정 영수증 표를 작성하고 각 사용자 및 영수증에 대해 계산 한 총액을 지불하십시오. 분석 쿼리는이를 효율적으로 해결합니다. 다른 솔루션은 효율성이 떨어집니다. 이것이 그들이 2003 SQL 표준의 일부인 이유입니다. (불행히도 Postgres에는 아직 없습니다. Grrr ...)


질문에 완전히 대답하려면 날짜 값을 반환해야합니다. 그것이 또 다른 first_value 절을 의미한다면 솔루션이 생각보다 복잡하고 max (date) 기반의 분석 방법이 더 잘 읽힐 것을 제안합니다.
David Aldridge

질문은 날짜를 반환하는 것에 대해 아무 것도 말하지 않습니다. 다른 FIRST (Date)를 추가하거나 날짜를 쿼리하고 외부 쿼리를 GROUP BY로 변경하여이를 수행 할 수 있습니다. 나는 첫 번째를 사용하고 최적화 프로그램이 한 번에 두 가지를 모두 계산할 것으로 기대합니다.
user11318

"질문은 날짜를 반환하는 것에 대해 아무 말도하지 않습니다"... 네, 맞습니다. 죄송합니다. 그러나 더 많은 FIRST_VALUE 절을 추가하면 매우 어려워집니다. 단일 창 정렬이지만 해당 행에 대해 20 개의 열을 반환하면 많은 코드를 작성했습니다.
David Aldridge

또한이 솔루션은 단일 사용자 ID에 최대 날짜와 다른 값을 갖는 여러 행이있는 데이터에 대해 결정적이지 않습니다. 대답보다 질문에 더 많은 결함이 있습니다.
David Aldridge

1
나는 그것이 고통스럽게 장황하다는 것에 동의합니다. 그러나 일반적으로 SQL의 경우가 아닙니까? 그리고 당신은 해결책이 비 결정적이라는 것이 옳습니다. 관계를 다루는 방법에는 여러 가지가 있으며 때로는 각각 원하는 방식으로 사용할 수 있습니다.
user11318

6

QUALIFY 절이 가장 단순하고 우수하지 않습니까?

select userid, my_date, ...
from users
qualify rank() over (partition by userid order by my_date desc) = 1

문맥 상, Teradata에서이 크기의 테스트는이 QUALIFY 버전에서는 17 초, '인라인 뷰'/ Aldridge 솔루션 # 1에서는 23 초에 실행됩니다.


1
이것은 내 의견으로는 가장 좋은 대답입니다. 그러나 rank()관계가있는 상황에서는 기능에 주의하십시오 . 둘 이상으로 끝날 수 rank=1있습니다. row_number()하나의 레코드 만 반환 하려면 사용 하는 것이 좋습니다.
cartbeforehorse

1
또한이 QUALIFY절은 Teradata에만 해당됩니다. Oracle에서는 (적어도) WHERE래핑 select 문에 절을 사용하여 쿼리를 중첩하고 필터링해야합니다 (아마도 성능에 영향을 미칩니다).
cartbeforehorse

5

에서 상위 n 쿼리를 분석 함수와 함께 Oracle 12c+사용 하여 하위 쿼리 없이 매우 간결하게이를 달성 할 수 있습니다 .rank

select *
from your_table
order by rank() over (partition by user_id order by my_date desc)
fetch first 1 row with ties;

위의 내용은 사용자 당 최대 my_date를 가진 모든 행을 반환합니다.

당신이 최대 날짜가 하나 개의 행을 원하는 경우, 다음을 대체 rank와 함께 row_number:

select *
from your_table
order by row_number() over (partition by user_id order by my_date desc)
fetch first 1 row with ties; 

5

사용 ROW_NUMBER()하강 순위에 고유을 할당 할 DateUserId각의 첫 번째 행에 다음 필터를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;

5

PostgreSQL 8.4 이상에서는 다음을 사용할 수 있습니다.

select user_id, user_value_1, user_value_2
  from (select user_id, user_value_1, user_value_2, row_number()
          over (partition by user_id order by user_date desc) 
        from users) as r
  where r.row_number=1

3

나는 당신이 shuold가 이전 쿼리에 대해이 변형을 만듭니다 :

SELECT UserId, Value FROM Users U1 WHERE 
Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)

3
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  

3

직장에서 "실시간"예제를 작성해야했습니다. :)

이것은 같은 날짜 에 UserId에 대한 여러 값을 지원 합니다.

열 : UserId, 값, 날짜

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
)

MAX 대신 FIRST_VALUE을 (를) 사용하고 Explain Plan에서 찾아 볼 수 있습니다. 나는 그것을 가지고 놀 시간이 없었다.

물론 거대한 테이블을 검색하는 경우 쿼리에 FULL 힌트를 사용하는 것이 좋습니다.


3
select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))

2

이런 식으로 생각합니다. (구문 실수로 나를 용서하십시오.이 시점에서 HQL을 사용하는 데 익숙합니다!)

편집 : 또한 질문을 잘못 읽으십시오! 검색어를 수정했습니다 ...

SELECT UserId, Value
FROM Users AS user
WHERE Date = (
    SELECT MAX(Date)
    FROM Users AS maxtest
    WHERE maxtest.UserId = user.UserId
)

은 "각 사용자 아이디에 대해"조건에 부합하지 않는다
데이비드 드리지

어디에서 실패할까요? Users의 모든 UserID에 대해 해당 UserID를 포함하는 하나 이상의 행이 반환됩니다. 아니면 어딘가에 특별한 경우가 빠져 있습니까?
jdmichal

2

(T-SQL) 먼저 모든 사용자와 최대 날짜를 얻습니다. maxdates에서 사용자에 해당하는 값을 찾으려면 테이블과 결합하십시오.

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

여기에 대한 답변은 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)

그리고 더 어려운 예는 설명이 필요하며 시간이 부족합니다.

2008 년에 가장 인기있는 책, 즉 2008 년에 가장 많이 빌리는 책 (ISBN 및 제목)을 제공하십시오.

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);

희망이 도움이 되길 바랍니다 .. :)

감사합니다, 거스


허용되는 답변은 "Oracle 전용"이 아닙니다. 표준 SQL (많은 DBMS에서 지원)
a_horse_with_no_name

2

주어진 사용자 ID에 대해 날짜가 고유하다고 가정하면 다음과 같은 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

나는 파티에 상당히 늦었지만 다음과 같은 핵이 상관 하위 쿼리와 모든 분석 기능을 능가하지만 한 가지 제한이 있습니다. 값은 문자열로 변환해야합니다. 따라서 날짜, 숫자 및 기타 문자열에서 작동합니다. 코드는 잘 보이지 않지만 실행 프로필은 훌륭합니다.

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

이 코드가 제대로 작동하는 이유는 테이블을 한 번만 스캔하면되기 때문입니다. 인덱스가 필요하지 않으며 가장 중요한 것은 대부분의 분석 기능이 수행하는 테이블을 정렬 할 필요가 없다는 것입니다. 단일 사용자 ID에 대한 결과를 필터링해야하는 경우 색인이 도움이됩니다.


그것은 대부분에 비해 좋은 실행 계획이지만, 모든 트릭을 몇 개 이상의 필드에 적용하는 것은 번거롭고 반대 할 수 있습니다. 그러나 매우 흥미로운-감사합니다. sqlfiddle.com/#!4/2749b5/23
Used_By_Already

지루해질 수있는 것이 맞습니다. 이것이 쿼리 성능이 필요할 때만 수행해야하는 이유입니다. ETL 스크립트의 경우가 종종 있습니다.
aLevelOfIndirection

이거 좋은데. LISTAGG를 사용하여 비슷한 것을했지만 추한 것처럼 보입니다. postgres는 array_agg를 사용하는 것이 더 나은 대안입니다. 내 대답은 : 참조
브루노 Calza

1
select userid, value, date
  from thetable t1 ,
       ( select t2.userid, max(t2.date) date2 
           from thetable t2 
          group by t2.userid ) t3
 where t3.userid t1.userid and
       t3.date2 = t1.date

이모 작동합니다. HTH


1

나는 이것이 작동해야한다고 생각합니까?

Select
T1.UserId,
(Select Top 1 T2.Value From Table T2 Where T2.UserId = T1.UserId Order By Date Desc) As 'Value'
From
Table T1
Group By
T1.UserId
Order By
T1.UserId

1

먼저 최상위 답변에 따라 질문을 잘못 읽으십시오. 다음은 올바른 결과를 보여주는 완전한 예입니다.

CREATE TABLE table_name (id int, the_value varchar(2), the_date datetime);

INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'a','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'b','2/2/2002');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'c','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'d','3/3/2003');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'e','3/3/2003');

-

  select id, the_value
      from table_name u1
      where the_date = (select max(the_date)
                     from table_name u2
                     where u1.id = u2.id)

-

id          the_value
----------- ---------
2           d
2           e
1           b

(3 row(s) affected)

1

또한 중복을 처리합니다 (각 user_id에 대해 한 행씩 반환).

SELECT *
FROM (
  SELECT u.*, FIRST_VALUE(u.rowid) OVER(PARTITION BY u.user_id ORDER BY u.date DESC) AS last_rowid
  FROM users u
) u2
WHERE u2.rowid = u2.last_rowid

1

방금 이것을 테스트했는데 로깅 테이블에서 작동하는 것 같습니다.

select ColumnNames, max(DateColumn) from log  group by ColumnNames order by 1 desc

1

다음과 같이 간단해야합니다.

SELECT UserId, Value
FROM Users u
WHERE Date = (SELECT MAX(Date) FROM Users WHERE UserID = u.UserID)

1

파티션 KEEP, DENSE_RANK 개념이없는 MySQL 용 솔루션.

select userid,
       my_date,
       ...
from
(
select @sno:= case when @pid<>userid then 0
                    else @sno+1
    end as serialnumber, 
    @pid:=userid,
       my_Date,
       ...
from   users order by userid, my_date
) a
where a.serialnumber=0

참조 : http://benincampus.blogspot.com/2013/08/select-rows-which-have-maxmin-value-in.html


이 "작동하지 않습니다 너무 다른 DB를에 ". 이것은 비슷한 변수 개념을 가지고 있기 때문에 MySQL과 SQL Server에서만 작동합니다. Oracle, Postgres, DB2, Derby, H2, HSQLDB, Vertica, Greenplum에서는 확실히 작동하지 않습니다. 또한 허용되는 답변은 표준 ANSI SQL입니다 (아직 MySQL 만 지원하지 않음)
a_horse_with_no_name

말, 당신이 옳은 것 같아요. 다른 DB 또는 ANSI에 대한 지식이 없습니다. 내 솔루션은 MySQL의 문제를 해결할 수 있으며 ANSI SQL은 표준 방식으로 해결할 수 없습니다.
벤 린

1

Postgres를 사용하는 경우 다음 array_agg과 같이 사용할 수 있습니다

SELECT userid,MAX(adate),(array_agg(value ORDER BY adate DESC))[1] as value
FROM YOURTABLE
GROUP BY userid

Oracle에 익숙하지 않습니다. 이것이 내가 생각해 낸 것입니다

SELECT 
  userid,
  MAX(adate),
  SUBSTR(
    (LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)),
    0,
    INSTR((LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)), ',')-1
  ) as value 
FROM YOURTABLE
GROUP BY userid 

두 쿼리 모두 허용 된 답변과 동일한 결과를 반환합니다. SQLFiddles를 참조하십시오.

  1. 허용 된 답변
  2. Postgres를 사용한 솔루션
  3. 오라클과의 내 솔루션

0

(UserID, Date)가 고유 한 경우, 즉 동일한 사용자에 대해 날짜가 두 번 나타나지 않는 경우 :

select TheTable.UserID, TheTable.Value
from TheTable inner join (select UserID, max([Date]) MaxDate
                          from TheTable
                          group by UserID) UserMaxDate
     on TheTable.UserID = UserMaxDate.UserID
        TheTable.[Date] = UserMaxDate.MaxDate;

나는 당신도 UserID에 의해 가입해야한다고 생각합니다
Tom H

0
select   UserId,max(Date) over (partition by UserId) value from users;

2
이것은 사용자 당 하나의 행이 아닌 모든 행을 반환합니다.
Jon Heller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.