Pergunta

Eu tenho duas tabelas com uma relação 1: n: "conteúdo" e "-content versionadas-data" (por exemplo, uma entidade artigo e todas as versões criadas do mesmo artigo). Eu gostaria de criar uma exibição que exibe a versão topo de cada "conteúdo".

Atualmente eu usar essa consulta (com uma subconsulta simples):

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

A subconsulta é realmente uma consulta para a mesma mesa que extrai a versão mais alto de um item específico. Observe que os itens de versão terá o mesmo fk_idothertable.

No SQL Server eu tentei criar uma visão indexada desta consulta, mas parece que eu não sou capaz desde subconsultas não são permitidos em exibições indexadas . Então ... aqui está a minha pergunta ... Você pode pensar em uma maneira de converter essa consulta para algum tipo de consulta com junções?

Parece que exibições indexadas não pode conter:

  • subqueries
  • expressões de tabela comum
  • tabelas derivadas
  • TENDO cláusulas

Estou desesperada. Quaisquer outras ideias são bem-vindas: -)

Muito obrigado!

Foi útil?

Solução

Isso provavelmente não vai ajudar se a tabela já está em produção, mas o caminho certo para modelar isto é fazer version = 0 a versão permanente e sempre incrementar a versão do material mais antigo. Então, quando você inserir uma nova versão que você diria:

UPDATE thetable SET version = version + 1 WHERE id = :id
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...)

Em seguida, essa consulta seria apenas

SELECT id, title, ... FROM thetable WHERE version = 0

Não subqueries, nenhuma agregação MAX. Você sempre sabe o que a versão atual. Você nunca tem que selecionar max (versão), a fim de inserir o novo registro.

Outras dicas

Talvez algo assim?

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)

Apenas um palpite ...

Você pode ser capaz de fazer o MAX uma mesa alias que faz GROUP BY.

Pode parecer algo como isto:

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

Eu acho FerranB estava perto, mas não chegou a ter o agrupamento de direita:

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

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

Eu não sei o quão eficiente este seria, mas:

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

Assim ... Presumo que o 'mytable' na subconsulta foi uma tabela real diferente ... então eu o chamei mytable2. Se fosse a mesma tabela, então este será ainda trabalho, mas então eu imagino que fk_idothertable será apenas '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

Espero que isso ajude

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top