我有一个带有“版本控制”方案的简单表:
Version | PartKey1 | PartKey2 | Value
1 | 0 | 0 | foo
2 | 0 | 0 | bar
1 | 1 | 0 | foobar
此表格中等(完整版约100 000行)。在开始时,它加载了包含完整快照的版本1,并且随着时间的推移添加了增量更新,但我们希望保留旧版本,因此它们会添加一个递增的“版本”编号(此处为2)。 / p>
在阅读数据时,我希望能够指定最大版本,如果可能的话,我希望只检索我感兴趣的“行”。
例如:指定2作为最大版本,我想在上表中只检索2行的查询:
Version | PartKey1 | PartKey2 | Value
2 | 0 | 0 | bar
1 | 1 | 0 | foobar
行:
1 | 0 | 0 | foo
被丢弃,因为此行的版本2
更新。
我想知道在SQL查询中这样的选择是否可行/可取。我可以在应用程序端进行过滤,但显然这意味着从数据库中提取无用的资源,所以如果可能(并且在数据库方面便宜),我宁愿将这项工作卸载到数据库。
答案 0 :(得分:5)
你可以这样做:
SELECT v1.*
FROM versioningscheme v1
LEFT JOIN versioningscheme v2
ON v2.partkey1 = v1.partkey1 AND v2.partkey2 = v1.partkey2
AND v2.version > v1.version
WHERE v2.version IS NULL
使用NULL检测的左连接非常强大且未充分利用。当没有匹配时返回空值(显然,当你在v1中有最大行时,你不能在v2中获得满足连接条件的行)。
答案 1 :(得分:2)
select t.*
from MyTable t
inner join (
select PartKey1, PartKey2, max(Version) as MaxVersion
from MyTable
where Version <= 2
group by PartKey1, PartKey2
) tm on t.PartKey1 = tm.PartKey1
and t.PartKey2 = tm.PartKey2
and t.Version = tm.MaxVersion
答案 2 :(得分:2)
这适用于时变数据(您选择在特定时间窗口内查找最新值),这是完全合理的。
在您的情况下,ROW_NUMBER()允许仅解析一次数据,而不是多次。使用适当的INDEX,例如(PartKey1, PartKey2, Version)
,这应该非常快......
SELECT
*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY PartKey1, PartKey2 ORDER BY Version DESC) AS reversed_version
FROM
MyTable
WHERE
Version <= <MaxVersionParamter>
)
AS data
WHERE
reversed_version = 1