SQL 选择具有与条件匹配的最新时间戳的行的最佳方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/285477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 00:13:39  来源:igfitidea点击:

Best way to select the row with the most recent timestamp that matches a criterion

sqloracle

提问by George Mauer

This is something that comes up so often I almost stopped thinking about it but I'm almost certain that I'm not doing this the best way.

这是经常出现的事情,我几乎停止思考它,但我几乎可以肯定我不是最好的方法。

The question: Suppose you have the following table

问题:假设你有下表

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

What is the best way to select the TEST_VALUE associated with the most recently updated row where FOREIGN_KEY = 10?

选择与 FOREIGN_KEY = 10 的最近更新的行关联的 TEST_VALUE 的最佳方法是什么?

EDIT:Let's make this more interesting as the answers below simply go with my method of sorting and then selecting the top row. Not bad but for large returns the order by would kill performance. So bonus points: how to do it in a scalable manner (ie without the unnecessary order by).

编辑:让我们让这更有趣,因为下面的答案只是按照我的排序方法然后选择顶行。不错,但对于大额回报,order by 会降低性能。所以加分点:如何以可扩展的方式做到这一点(即没有不必要的 order by)。

回答by Justin Cave

Analytic functions are your friends

分析函数是你的朋友

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

You can also extend that to get the information for the entire row

您还可以扩展它以获取整行的信息

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

And analytic approaches are generally pretty darned efficient.

分析方法通常非常有效。

I should also point out that analytic functions are relatively new, so if you are on something earlier than 9.0.1, this may not work. That's not a huge population any more, but there are always a few folks stuck on old versions.

我还应该指出,分析函数相对较新,因此如果您使用的是 9.0.1 之前的版本,这可能不起作用。这不再是一个庞大的人口,但总有一些人坚持使用旧版本。

回答by Tomalak

Either use a sub-query

要么使用子查询

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

or select the TOP 1 record with

或选择 TOP 1 记录

ORDER BY updated DESC

In Oracle syntax this would be:

在 Oracle 语法中,这将是:

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

回答by Gary Myers

Firstly, you will always need to look at all the rows with that foreign key, and find the one with the highest UPDATED value...which means a MAX or ORDER BY. The efficiency of the comparison is partly up to the optimizer, so will depend on your Oracle version. Your data structures may have a greater impact on actual performance though. An index on FOREIGN_KEY, UPDATED DESC, TEST_VALUE would probably give the most scalable solution for querying as Oracle will normally be able to give the answer just accessing a single leaf block. There may be a detrimental impact on inserts as new records have to be inserted into that structure.

首先,您将始终需要查看具有该外键的所有行,并找到具有最高 UPDATED 值的行……这意味着 MAX 或 ORDER BY。比较的效率部分取决于优化器,因此将取决于您的 Oracle 版本。不过,您的数据结构可能会对实际性能产生更大的影响。FOREIGN_KEY、UPDATED DESC、TEST_VALUE 上的索引可能会提供最具扩展性的查询解决方案,因为 Oracle 通常能够仅访问单个叶块就给出答案。由于必须将新记录插入到该结构中,因此可能会对插入产生不利影响。

回答by George Mauer

The probably inferior way that I currently go about doing something like this is

我目前做这样的事情的可能较差的方式是

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
)

but please StackOverflow Geniuses, teach me some tricks

但请 StackOverflow 天才们,教我一些技巧

回答by Paul Morgan

SELECT TEST_VALUE
  FROM TEST_TABLE
 WHERE UPDATED      = ( SELECT MAX(UPDATED)
                          FROM TEST_TABLE
                         WHERE FOREIGN_KEY = 10 )
   AND FOREIGN-KEY  = 10
   AND ROWNUM       = 1  -- Just in case records have the same UPDATED date

Rather that take the first record you could break a tie with the hightest ID or maybe least/largest TEST_VALUE.

而不是拿第一个记录,你可以打破与最高 ID 或最小/最大 TEST_VALUE 的平局。

An index of FOREIGN_KEY, UPDATED would help query performace.

FOREIGN_KEY、UPDATED 的索引将有助于查询性能。

回答by aaaantoine

Up until I read Justin Cave's answer, I've used the following pattern to grab the most recent records en masse.

在我阅读 Justin Cave 的回答之前,我一直使用以下模式来获取最新的记录。

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

This query finds the most recent updates for each foreign key in the table. Although Justin's answer is faster when the key is known, this query also works in SQL Server.

此查询查找表中每个外键的最新更新。尽管在知道密钥时 Justin 的回答会更快,但此查询也适用于 SQL Server。

回答by EvilTeach

Performance will depend on what is indexed. Here is a method.

性能将取决于索引的内容。这里有一个方法。

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

回答by Jason Slocomb

There is an oracle SQL faq here that may help you:

这里有一个 oracle SQL 常见问题解答可以帮助您:

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

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

回答by WW.

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

Oracle is smart enough to realize it only needs a single row from the inner select and it will do this efficiently.

Oracle 足够聪明,它意识到它只需要来自内部选择的一行,并且它会有效地做到这一点。

回答by FallenAvatar

wouldn't this work:

这行不通:

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

no need for a subquery...

不需要子查询...