Domanda

Ho due tabelle con una relazione 1: n: " content " e "quoted-content-data "" (ad esempio un'entità articolo e tutte le versioni create di quell'articolo). Vorrei creare una vista che mostri la versione superiore di ogni "contenuto".

Attualmente utilizzo questa query (con una semplice subquery):

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

La subquery è in realtà una query nella stessa tabella che estrae la versione più alta di un elemento specifico. Si noti che gli elementi con versione avranno la stessa fk_idothertable.

In SQL Server ho provato a creare una vista indicizzata di questa query ma sembra che io non sia in grado poiché le sottoquery non sono consentite nelle viste indicizzate . Quindi ... ecco la mia domanda ... Riesci a pensare a un modo per convertire questa query in una sorta di query con JOIN?

Sembra che le viste indicizzate non possano contenere:

  • subqueries
  • espressioni di tabella comuni
  • tabelle derivate
  • Clausole HAVING

Sono disperato. Altre idee sono benvenute :-)

Grazie mille!

È stato utile?

Soluzione

Questo probabilmente non aiuterà se la tabella è già in produzione ma il modo giusto per modellarlo è rendere version = 0 la versione permanente e incrementare sempre la versione del materiale OLDER. Quindi, quando si inserisce una nuova versione, si direbbe:

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

Quindi questa query sarebbe solo

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

Nessuna subquery, nessuna aggregazione MAX. Sai sempre qual è la versione attuale. Non devi mai selezionare max (versione) per inserire il nuovo record.

Altri suggerimenti

Forse qualcosa del genere?

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)

Solo un'ipotesi selvaggia ...

Potresti essere in grado di trasformare MAX in un alias di tabella che raggruppa per

Potrebbe assomigliare a questo:

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

Penso che FerranB fosse vicino ma non aveva il giusto raggruppamento:

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

Non so quanto sia efficiente, ma:

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

In questo modo ... Suppongo che il 'mytable' nella sottoquery fosse una tabella effettiva diversa ... così l'ho chiamato mytable2. Se fosse la stessa tabella allora funzionerà comunque, ma immagino che fk_idothertable sarà semplicemente "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

Spero che questo aiuti

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top