Frage

Ich habe zwei Tabellen mit einem 1: n-Beziehung: „Inhalt“ und „versioniert-Inhaltsdaten“ (zum Beispiel einer Artikel Einheit und alle Versionen dieses Artikels erstellt wird). Ich möchte eine Ansicht erstellen, die die Top-Version jedes „Inhalt“ angezeigt wird.

Zur Zeit verwende ich diese Abfrage (mit einer einfachen Unterabfrage):

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

Die Unterabfrage ist eigentlich eine Abfrage an die gleiche Tabelle, die die höchste Version eines bestimmten Elements extrahiert. Beachten Sie, dass der versioniert Artikel die gleichen fk_idothertable hat.

In SQL Server Ich habe versucht, eine indizierte Sicht dieser Abfrage zu erstellen, aber es scheint, dass ich nicht in der Lage bin, da Unterabfragen sind in indizierte Sichten nicht erlaubt . So ... hier ist meine Frage ... Können Sie einen Weg finden, diese Abfrage eine Art von Abfrage zu konvertieren mit JOIN?

Es scheint, wie indizierte Sichten können nicht enthalten:

  • Unterabfragen
  • allgemeine Tabellenausdrücke
  • abgeleitete Tabellen
  • HAVING-Klauseln

Ich bin verzweifelt. Jede andere Ideen sind willkommen: -)

Vielen Dank!

War es hilfreich?

Lösung

Dies wird wahrscheinlich nicht helfen, wenn die Tabelle bereits in der Produktion ist, aber der richtige Weg, dies zu modellieren ist auf Version = 0 die permanente Version zu machen und immer die Version von älterem Material zu erhöhen. Also, wenn Sie eine neue Version einsetzen würden Sie sagen:

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

Dann würde diese Abfrage nur sein

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

Keine Unterabfragen, keine MAX-Aggregation. Sie wissen immer, was die aktuelle Version ist. Sie müssen sich nie wählen max (Version), um den neuen Datensatz einzufügen.

Andere Tipps

Vielleicht so etwas wie das?

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)

Nur eine wilde Vermutung ...

Sie könnten in der Lage sein, die MAX eine Tabelle alias zu machen, die Gruppe hat durch.

Es könnte wie folgt aussehen:

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

Ich denke, FerranB Nähe war, aber hatte nicht ganz die Gruppierung rechts:

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

Ich weiß nicht, wie effizient dies sei, aber:

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

So ... Ich gehe davon aus, dass das ‚mytable‘ in der Unterabfrage war eine andere aktuelle Tabelle ... so rief ich es mytable2. Wenn es der gleiche Tisch ist, dann wird dies immer noch funktionieren, aber dann denke ich, dass fk_idothertable wird nur ‚id‘ sein.


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

Hope, das hilft

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top