programing

기준과 일치하는 가장 최근 타임스탬프가 있는 행을 선택하는 가장 좋은 방법

yellowcard 2023. 11. 1. 22:15
반응형

기준과 일치하는 가장 최근 타임스탬프가 있는 행을 선택하는 가장 좋은 방법

이것은 너무 자주 언급되는 것이라 거의 생각을 접을 뻔했지만 저는 이것을 최선의 방법으로 하고 있지 않다고 거의 확신합니다.

질문:다음 표가 있다고 가정합니다.

CREATE TABLE TEST_TABLE
(
  ID          INTEGER,
  TEST_VALUE  NUMBER,
  UPDATED     DATE,
  FOREIGN_KEY INTEGER
);

FORINE_KEY = 10인 가장 최근에 업데이트된 행과 관련된 TEST_VALUE를 선택하는 가장 좋은 방법은 무엇입니까?

편집: 아래의 답은 단순히 제 방법으로 정렬한 다음 맨 위 행을 선택하는 것이므로 이 문제를 더 흥미롭게 만들어 보겠습니다.나쁘지는 않지만 대량 반품의 경우에는 성능이 저하될 수 있습니다.따라서 보너스 포인트: 확장 가능한 방식으로 수행하는 방법(즉, 불필요한 주문 없이).

분석 기능은 당신의 친구입니다.

SQL> select * from test_table;

        ID TEST_VALUE UPDATED   FOREIGN_KEY
---------- ---------- --------- -----------
         1         10 12-NOV-08          10
         2         20 11-NOV-08          10

SQL> ed
Wrote file afiedt.buf

  1* select * from test_table
SQL> ed
Wrote file afiedt.buf

  1  select max( test_value ) keep (dense_rank last order by updated)
  2  from test_table
  3* where foreign_key = 10
SQL> /

MAX(TEST_VALUE)KEEP(DENSE_RANKLASTORDERBYUPDATED)
-------------------------------------------------
                                               10

전체 행에 대한 정보를 얻기 위해 확장할 수도 있습니다.

SQL> ed
Wrote file afiedt.buf

  1  select max( id ) keep (dense_rank last order by updated) id,
  2         max( test_value ) keep (dense_rank last order by updated) test_value
,
  3         max( updated) keep (dense_rank last order by updated) updated
  4  from test_table
  5* where foreign_key = 10
SQL> /

        ID TEST_VALUE UPDATED
---------- ---------- ---------
         1         10 12-NOV-08

분석적 접근 방식은 일반적으로 상당히 효율적입니다.

분석 기능은 비교적 새로운 기능이므로 9.0.1 이전 버전에서는 작동하지 않을 수 있습니다.더 이상 인구가 많지는 않지만, 항상 오래된 버전을 사용하는 사람들이 몇 명 있습니다.

하위 쿼리를 사용합니다.

WHERE updated = (SELECT MAX(updated) ...)

또는 TOP 1 레코드를 선택합니다.

ORDER BY updated DESC

Oracle 구문에서는 다음과 같습니다.

SELECT 
  * 
FROM 
(
  SELECT * FROM test_table
  ORDER BY updated DESC
)
WHERE 
  ROWNUM = 1

첫째, 항상 해당 외래 키로 모든 행을 보고 업데이트된 값이 가장 높은 행을 찾아야 합니다.MAX나 ORDER BY를 의미합니다.비교의 효율성은 부분적으로 Optimizer에 달려 있으므로 Oracle 버전에 따라 달라집니다.데이터 구조가 실제 성능에 더 큰 영향을 미칠 수도 있습니다.FOREAN_KEY, UPDATED DESC, TEST_VALUE의 인덱스는 Oracle이 일반적으로 단일 리프 블록에 액세스하는 것만으로 답변을 제공할 수 있기 때문에 쿼리에 가장 확장성이 높은 솔루션을 제공할 수 있습니다.해당 구조물에 새 레코드를 삽입해야 하므로 삽입물에 좋지 않은 영향을 미칠 수 있습니다.

제가 지금 이런 일을 하고 있는 열등한 방법은

SELECT TEST_VALUE
FROM TEST_TABLE
WHERE ID = (
  SELECT ID
  FROM (
    SELECT ID
    FROM TEST_TABLE
    WHERE FOREIGN_KEY = 10
    ORDER BY UPDATED DESC
  )
  WHERE ROWNUM = 1
)

하지만 오버플로우 천재들을 쌓아두고, 몇 가지 기술을 가르쳐주세요.

테스트 선택_VALUEFROM TEST_TABLEWHERE UPDATED = (최대 선택(업데이트됨)FROM TEST_TABLE여기서 FORINE_KEY = 10 )AND 외국인 키 = 10AND ROWNUM = 1 -- 레코드의 업데이트 날짜가 동일한 경우를 위해

첫 번째 기록을 사용하는 대신 가장 높은 ID 또는 가장 작은/가장 큰 TEST_VALUE로 동점을 만들 수 있습니다.

FORINE_KEY의 인덱스인 UPDATE가 쿼리 성능에 도움이 될 것입니다.

저스틴 케이브의 답변을 읽기 전까지는 다음과 같은 패턴을 사용하여 최근 기록을 대량으로 수집했습니다.

WITH test_table_ranked AS (
    SELECT
        test_table.*,
        ROW_NUMBER() OVER (
            PARTITION BY foreign_key ORDER BY updated DESC
        ) AS most_recent
    FROM
        test_table
)
SELECT *
FROM test_table_ranked
WHERE most_recent = 1
-- AND foreign_key = 10

이 쿼리는 테이블에서 각 외부 키에 대한 최신 업데이트를 찾습니다.키를 알면 저스틴의 대답이 더 빠르지만, 이 쿼리는 SQL Server에서도 작동합니다.

성능은 색인화된 항목에 따라 달라집니다.여기 방법이 있습니다.

WITH 
ten AS
(
    SELECT *
    FROM TEST_TABLE
    WHERE FOREIGH_KEY = 10
)
SELECT TEST_VALUE 
FROM ten
WHERE UPDATED = 
(
    SELECT MAX(DATE)
    FROM ten
)

다음과 같은 도움이 되는 Oracle SQL FAQ가 있습니다.

http://www.orafaq.com/wiki/SQL_FAQ

select test_value
from
(
  select test_value 
  from test_table
  where foreign_key=10
  order by updated desc
)
where rownum = 1

Oracle은 내부 선택 항목에서 하나의 행만 필요로 하며 이를 효율적으로 수행할 수 있다는 것을 충분히 현명하게 인식합니다.

이것은 효과가 있지 않을까요?

SELECT TOP 1 ID
FROM test_table
WHERE FOREIGN_KEY = 10
ORDER BY UPDATED DESC

서브쿼리는 필요없습니다...

언급URL : https://stackoverflow.com/questions/285477/best-way-to-select-the-row-with-the-most-recent-timestamp-that-matches-a-criteri

반응형