我想查询一个巨型表(SQL Server)以获取一组记录的最新版本,例如
表:
Id, key, Ver
1, A, 1
2, B, 1
3, A, 2
4, B, 2
5,B, 3
结果:
Id, Key, Ver
3, A, 2
5, B, 3
here中提到的连接方法可以正常工作,但只有在想要获取所有密钥的最新版本时才能正常工作,但如果我们只关心密钥子集,则连接将成为过多的开销。所以我想问一下我们是否应该进行循环
select top 1 * from table where key = 'A' order by ver desc
或
select max(ver), key from table where key in ('A', 'B') group by key
还是有更好的方法呢?欢呼声
答案 0 :(得分:2)
基本上,一次一个地循环一组键并执行n
次操作对于任何RDBMS都是一种糟糕的方法。它阻止查询引擎优化并保证n
搜索\扫描表\索引。
如果您可以将查询表达为基于集合的操作,这将允许查询引擎完全优化您的操作,从而创建更加优化的查询计划。
如果您使用的是SQL Server 2008或更高版本,请使用RANK
,
SELECT
[Id],
[Key],
[Ver]
FROM
[Table]
WHERE
RANK() OVER (PARTITION BY [Key], ORDER BY [Ver] DESC) = 1;
使用更通用的SQL,
SELECT
[T1].[Id],
[T2].[Key],
[T2].[Ver]
FROM (
SELECT
[Key]
MAX([Ver]) [Ver]
FROM
[Table]
WHERE
[Key] IN ('A', 'B')
GROUP BY
[Key]) [T2]
JOIN
[Table] [T1]
ON [T1].[Key] = [T2].[Key] AND [T1].[Ver] = [T2].[Ver];
要确保两个查询的效果,请在Key
然后Ver
上创建覆盖索引。
CREATE UNIQUE NONCLUSTERED INDEX [IX_Table_Key_Ver]
ON [Table] ([Key], [Ver] DESC);
答案 1 :(得分:0)
使用子选项查找密钥的最大值:
select * from table t1
where ver = (select max(ver) from table
where key = t1.key)
答案 2 :(得分:0)
IMO,你的第二个解决方案应该表现得好,如果不是比这里提到的任何其他解决方案更好。
select max(ver), key from table where key in ('A', 'B') group by key
另外,在key
列上创建索引。
编辑:
对于Max version row ID
值,您可以使用CTE
WITH CTE AS
(
select max(ver) VER, key from table where key in ('A', 'B') group by key
)
SELECT * FROM TABLE
INNER JOIN CTE
ON CTE.KEY=TABLE.KEY
AND CTE.VER=TABLE.VER
答案 3 :(得分:0)
这是另一种使用分析函数的方法,例如row_number
:
select *
from (
select *, row_number() over (partition by key order by id desc) rn
from yourtable
) t
where rn = 1
答案 4 :(得分:0)
一般不要使用TOP 1的判断,ROW_NUMBER()更好。游标也不是一个好主意(忽略我的订单的技术性!)。
E.g。
SELECT
A.*
FROM
(
SELECT
ID
,Ver
,ROW_NUMBER() OVER(PARTITION BY Key ORDER BY Ver DESC) AS Seq
FROM
Table
) AS A
WHERE
A.Seq = 1
应该做得很好,我相信你的要求。