这是经常出现的事情,我几乎不再考虑它了,但我几乎可以肯定我不是这样做的最佳方式。
问题:假设您有下表
CREATE TABLE TEST_TABLE
(
ID INTEGER,
TEST_VALUE NUMBER,
UPDATED DATE,
FOREIGN_KEY INTEGER
);
选择与FOREIGN_KEY = 10的最近更新的行相关联的TEST_VALUE的最佳方法是什么?
编辑:让我们更加有趣,因为下面的答案只是采用我的排序方法,然后选择顶行。不错,但对于大量退货,订单会扼杀性能。所以奖励积分:如何以可扩展的方式进行(即没有不必要的顺序)。
答案 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可以帮到你:
答案 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
不需要子查询...