我有两个具有 1:n 关系的表:“内容”和“版本化内容数据”(例如,文章实体和该文章创建的所有版本)。我想创建一个显示每个“内容”的顶部版本的视图。
我使用这个查询(带有一个简单的子查询):
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1
WHERE (version = (
SELECT MAX(version) AS topversion
FROM mytable
WHERE (fk_idothertable = t1.fk_idothertable)))
子查询是针对同一个表提取特定项目的最高版本。版本控制的项目将具有相同的 fk_idothertable。
在 SQL Server 中,我尝试创建此查询的索引视图,但索引视图中不允许使用子查询。
有什么方法可以将此查询转换为带有 JOIN 的查询?
索引视图似乎不能包含:
如果表已经在生产中,这可能不会有帮助,但建模的正确方法是使 version = 0 成为永久版本,并始终增加旧材料的版本。因此,当您插入新版本时,您会说:
UPDATE thetable SET version = version + 1 WHERE id = :id
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...)
那么这个查询就是
SELECT id, title, ... FROM thetable WHERE version = 0
没有子查询,没有 MAX 聚合。您始终知道当前版本是什么。您无需选择 max(version) 即可插入新记录。
也许是这样的?
SELECT
t2.id,
t2.title,
t2.contenttext,
t2.fk_idothertable,
t2.version
FROM mytable t1, mytable t2
WHERE t1.fk_idothertable == t2.fk_idothertable
GROUP BY t2.fk_idothertable, t2.version
HAVING t2.version=MAX(t1.version)
只是一个疯狂的猜测......
您也许可以将 MAX 设置为执行分组依据的表别名。
它可能看起来像这样:
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1 JOIN
(SELECT fk_idothertable, MAX(version) AS topversion
FROM mytable
GROUP BY fk_idothertable) as t2
ON t1.version = t2.topversion
我认为 FerranB 很接近,但分组不太正确:
with
latest_versions as (
select
max(version) as latest_version,
fk_idothertable
from
mytable
group by
fk_idothertable
)
select
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable,
t1.version
from
mytable as t1
join latest_versions on (t1.version = latest_versions.latest_version
and t1.fk_idothertable = latest_versions.fk_idothertable);
M
我不知道这有多有效,但是:
选择 t1.*, t2.版本 来自 mytable AS t1 加入 ( 选择 mytable.fk_idothertable, MAX(mytable.version) AS 版本 来自我的表 ) t2 ON t1.fk_idothertable = t2.fk_idothertable
如果 SQL Server 接受 LIMIT 子句:
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1
ORDER BY t1.version
DESC LIMIT 1;
(DESC 表示降序排序。)
LIMIT 1 仅选择第一行并且 DBMS 通常会进行良好的优化。
像这样...我假设子查询中的“mytable”是一个不同的实际表...所以我将其称为mytable2。如果是同一张表,那么这仍然有效,但我想 fk_idothertable 将只是“id”。
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1
INNER JOIN (SELECT MAX(Version) AS topversion,fk_idothertable FROM mytable2 GROUP BY fk_idothertable) t2
ON t1.id = t2.fk_idothertable AND t1.version = t2.topversion
希望这有帮助