我有两个表与1:n关系:“content”和“versioned-content-data”(例如,文章实体和该文章创建的所有版本)。我想创建一个显示每个“内容”的顶级版本的视图。
目前我使用此查询(使用简单的子查询):
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查询吗?
似乎索引视图不能包含:
我很绝望。欢迎任何其他想法: - )
非常感谢!
答案 0 :(得分:13)
如果表已经在生产中,这可能无济于事,但正确的建模方法是将version = 0作为永久版本,并始终增加OLDER材料的版本。因此,当您插入新版本时,您会说:
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(版本)以插入新记录。
答案 1 :(得分:3)
也许是这样的?
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)
只是猜测......
答案 2 :(得分:0)
我不知道这会有多高效,但是:
SELECT t1.*, t2.version FROM mytable AS t1 JOIN ( SElECT mytable.fk_idothertable, MAX(mytable.version) AS version FROM mytable ) t2 ON t1.fk_idothertable = t2.fk_idothertable
答案 3 :(得分:0)
您可以使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
答案 4 :(得分:0)
我认为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);
中号
答案 5 :(得分:0)
If SQL Server accepts LIMIT clause, I think the following should work:
SELECT
t1.id,
t1.title,
t1.contenttext,
t1.fk_idothertable
t1.version
FROM mytable as t1 ordery by t1.version DESC LIMIT 1;
(DESC - For descending sort; LIMIT 1 chooses only the first row and
DBMS usually does good optimization on seeing LIMIT).
答案 6 :(得分:-1)
像这样...我假设子查询中的'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
希望这有帮助