Вопрос

У меня есть две таблицы с отношением 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?

Кажется, что индексированные представления не могут содержать:

  • подзапросы
  • общие табличные выражения
  • производные таблицы
  • HAVING предложения

Я в отчаянии.Любые другие идеи приветствуются :-)

Большое спасибо!

Это было полезно?

Решение

Вероятно, это не поможет, если таблица уже находится в производстве, но правильный способ смоделировать это — сделать версию = 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);

М

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).

Не знаю, насколько это будет эффективно, но:

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

Вот так... Я предполагаю, что "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

Надеюсь это поможет

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top