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

时间:2008-11-12 21:40:46

标签: sql oracle

这是经常出现的事情,我几乎不再考虑它了,但我几乎可以肯定我不是这样做的最佳方式。

问题:假设您有下表

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

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

编辑:让我们更加有趣,因为下面的答案只是采用我的排序方法,然后选择顶行。不错,但对于大量退货,订单会扼杀性能。所以奖励积分:如何以可扩展的方式进行(即没有不必要的顺序)。

10 个答案:

答案 0 :(得分:13)

分析功能是你的朋友

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的东西,这可能不起作用。这不再是一个庞大的人口,但总有一些人坚持旧版本。

答案 1 :(得分:3)

使用子查询

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

我目前正在做的事情可能是低劣的方式

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
)

但请StackOverflow Geniuses,教我一些技巧

答案 4 :(得分:1)

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

相反,你可以使用第一条记录打破最高ID或者最小/最大TEST_VALUE。

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

答案 5 :(得分:1)

在我读到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

此查询查找表中每个外键的最新更新。虽然Justin的答案在密钥已知时速度更快,但此查询也适用于SQL Server。

答案 6 :(得分:0)

性能取决于索引的内容。 这是一种方法。

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

答案 7 :(得分:0)

这里有一个oracle SQL faq可以帮到你:

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

答案 8 :(得分:-1)

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

Oracle非常聪明地意识到它只需要内部选择中的一行,它就能有效地完成这一任务。

答案 9 :(得分:-1)

这不会起作用:

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

不需要子查询...