9

我有两个具有 1:n 关系的表:“内容”和“版本化内容数据”(例如,文章实体和该文章创建的所有版本)。我想创建一个显示每个“内容”的顶级版本的视图。

目前我使用这个查询(带有一个简单的子查询):

选择
   t1.id,
   t1.title,
   t1.contenttext,
   t1.fk_idothertable
   t1.版本
FROM mytable 作为 t1
WHERE (version = (SELECT MAX(version) AS topversion
                  来自我的表
                  WHERE (fk_idothertable = t1.fk_idothertable)))

子查询实际上是对提取特定项目的最高版本的同一个表的查询。请注意,版本化项目将具有相同的 fk_idothertable。

在 SQL Server 中,我尝试创建此查询的索引视图,但似乎我做不到,因为索引视图中不允许子查询。所以...这是我的问题...您能想出一种方法将此查询转换为某种带有 JOIN 的查询吗?

似乎索引视图不能包含:

  • 子查询
  • 公用表表达式
  • 派生表
  • HAVING 子句

我很绝望。欢迎任何其他想法:-)

非常感谢!

4

7 回答 7

14

如果表已经在生产中,这可能无济于事,但建模的正确方法是使 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(version) 来插入新记录。

于 2009-03-02T03:11:35.130 回答
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)

只是一个疯狂的猜测......

于 2009-03-02T01:12:53.963 回答
0

我不知道这会有多有效,但是:

选择 t1.*, t2.version
FROM mytable AS t1
    加入 (
        选择 mytable.fk_idothertable, MAX(mytable.version) AS 版本
        来自我的表
    ) t2 ON t1.fk_idothertable = t2.fk_idothertable
于 2009-03-02T01:05:24.683 回答
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
于 2009-03-02T01:05:33.013 回答
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);

于 2009-03-02T02:38:27.660 回答
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).
于 2012-05-23T14:38:53.467 回答
-2

像这样......我假设子查询中的“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

希望这可以帮助

于 2009-03-02T01:04:28.383 回答