Announcement

Collapse
No announcement yet.

Abfrage aller Werte einer Tabelle in der neuesten Version über 3 Tabellen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Abfrage aller Werte einer Tabelle in der neuesten Version über 3 Tabellen

    Hallo,

    Ich versuche gerade Eine Abfrage von Werten in beliebigen Versionen über drei Tabellen zu gestalten.

    Als PK dient jeweils die ID Spalte. Die Tabellen sehen wie folgt aus:

    Tabelle 1: Versionen

    Version_ID | Version | Value
    1 | 1 | 24
    2 | 1 | 10
    3 | 1 | 20
    4 | 1 | 30
    5 | 2 | 40
    6 | 3 | 50
    7 | 1 | 60


    Tabelle 2: Parameter

    Konstante_ID | Konstante
    1 | C1
    2 | C2
    3 | C3
    4 | C4


    Tabelle 3: Varianten

    Variante_ID | Beschreibung
    1 | Variante1
    2 | Variante2

    Da alle über eine N:M Beziehung miteinander verknüpft sind benötige ich eine Verknüpfungstabelle.

    Tabelle 4: Verknuepfungstabelle

    Konstante_ID | Version_ID | Variante_ID
    1 | 1 | 1
    2 | 2 | 1
    3 | 3 | 1
    4 | 4 | 1
    1 | 1 | 2
    2 | 2 | 2
    3 | 7 | 2
    4 | 4 | 2
    2 | 5 | 1
    2 | 6 | 1

    Es sind zunächst einmal jeder Variante alle Konstanten zugeordnet und jede Konstante kann in unterschiedlichen Versionen vorliegen bei unterschiedlichen Varianten.

    Die Abfrage soll nun Ein Ergebnis liefern das abhängig von der Variante für alle Konstanten die neuesten Version ausgibt, also im Prinzip eine Tabelle die folgendes ausgibt.

    Ergebnistabelle für Variante 1:

    Konstante_ID | Version_ID | Version | Value

    1 | 1 | 1 | 24
    2 | 6 | 3 | 50
    3 | 3 | 1 | 20
    4 | 4 | 1 | 30

    Ergebnistabelle für Variante 2:

    1 | 1 | 1 | 24
    2 | 2 | 1 | 10
    3 | 7 | 1 | 60
    4 | 4 | 1 | 30


    Mein Code:

    SELECT Versionen.*,Konstante
    FROM Versionen
    INNERJOIN
    Verknuepfungstabelle ON Verknuepfungstabelle.Version_ID = Versionen.Version_ID
    INNERJOIN
    Parameter ON Parameter.Konstante_ID = Verknuepfungstabelle.Konstante_ID
    INNERJOIN
    (SELECT Konstante_ID,MAX(Versionen.Version)AS High_Version
    FROM Parameter ,Versionen
    GROUPBY Konstante_ID)
    b ON b.Konstante_ID = Parameter.Konstante_ID
    AND b.High_Version = Versionen.Version
    AND Variante_ID = 1
    ORDERBY Parameter.Konstante_ID DESC

    Der Code spuckt aber leider nur ein Wert in der höchsten Version aus oder alle Werte in allen Versionen. Je nachdem ob die erste AND Zeile auskommentiert ist oder nicht. Komme leider nicht weiter und hoffe Ihr könnt mir da weiter helfen.













  • #2
    Originally posted by Froschn View Post
    ----
    Die Abfrage soll nun Ein Ergebnis liefern das abhängig von der Variante für alle Konstanten die neuesten Version ausgibt,
    ----
    Der Code spuckt aber leider nur ein Wert in der höchsten Version aus
    Ok, erste Frage:
    Was ist denn die "neueste Version"
    Laut Deiner Tabelle gibt es eine Version "1" in 4 Ausprägungen (Values) und einer scheinbar eindeutigen ID.
    (Die joinst du übrigens in deinem Statement bedingungslos mit Parameter, ist das gewollt und warum?)

    Außerdem:
    Die von Dir gezeigten Daten sind schon mal gut als Beispiel, es gibt aber keine technische Angabe darin, welche Spalten referenziert werden.
    Das kann man sich anhand der Namen und Deines Statements zusammeninterpretieren, aber das ist fehleranfällig (als Interpretation (z.b. meinerseits) und auch in der Entwicklung durch Dich und Deine Kollegen). Dafür gibt es Sprachkonstrukte, die es "sogar" der Datenbank erkennbar machen und für Klarheit sorgen > referentielle Constraints. Dabei handelt es sich um ein wesentliches Merkmal von relationalen Datenbanken.

    Comment


    • #3
      Originally posted by defo2 View Post

      Ok, erste Frage:
      Was ist denn die "neueste Version"
      Laut Deiner Tabelle gibt es eine Version "1" in 4 Ausprägungen (Values) und einer scheinbar eindeutigen ID.
      Es werden alle Werte in der Version 1 angelegt. Wenn jetzt ein Wert geändert wird zählt die Version eins hoch und ich möchte die Konstante mit dem neuen Wert abfragen aber zusätzlich auch die alte Version behalten.
      Die Version ist also über die Versions_ID eindeutig zuzuordnen, aber es sollen mehrere Versions_ID einer Konstante_ID zugeordnet werden, um bei einer Abfrage (der Query soll nicht bearbeitet werden) immer die neueste Version zu erhalten.

      Ich hab hier nochmal die Struktur mit den PK, FK hochgeladen.





      Attached Files
      Zuletzt editiert von Froschn; 28.03.2019, 12:17.

      Comment


      • #4
        Originally posted by Froschn View Post

        Es werden alle Werte in der Version 1 angelegt. Wenn jetzt ein Wert geändert wird zählt die Version eins hoch
        Sorry aber diese Beschreibung bekomme ich nicht mit den Daten in Tabelle Version Beitrag 1 in Verbindung. Vielleicht machst Du mal ein Beispiel:
        Datensätze Ursprungszustand
        Beschreibung der Änderung
        Datensätze nach Versionsänderung

        Comment


        • #5
          Also Im Ursprungszustand sehen die Daten so Aus.

          Tabelle 1: Versionen

          Version_ID | Version | Value
          1 | 1 | 24
          2 | 1 | 10
          3 | 1 | 20
          4 | 1 | 30


          Tabelle 2: Parameter

          Konstante_ID | Konstante
          1 | C1
          2 | C2
          3 | C3
          4 | C4

          Tabelle 3: Varianten

          Variante_ID | Beschreibung
          1 | Variante1
          2 | Variante2

          Tabelle 4: Verknuepfungstabelle

          Konstante_ID | Version_ID | Variante_ID
          1 | 1 | 1
          2 | 2 | 1
          3 | 3 | 1
          4 | 4 | 1
          1 | 1 | 2
          2 | 2 | 2
          3 | 3 | 2
          4 | 4 | 2


          Ergebnistabelle für Variante 1:

          Konstante_ID | Version_ID | Version | Value

          1 | 1 | 1 | 24
          2 | 2 | 1 | 10
          3 | 3 | 1 | 20
          4 | 4 | 1 | 30

          Ergebnistabelle für Variante 2:

          1 | 1 | 1 | 24
          2 | 2 | 1 | 10
          3 | 3 | 1 | 20
          4 | 4 | 1 | 30

          Änderung:
          In der Variante 1 wird jetzt für die Konstante C2 ein neuer Wert eingetragen z.B. 15 (also von 10 --> 15), wobei der alte Wert von 10 erhalten bleiben soll, allerdings in der Ergebnistabelle der Wert 15 abgefragt wird.

          Tabelle 1: Versionen

          Version_ID | Version | Value
          1 | 1 | 24
          2 | 1 | 10
          3 | 1 | 20
          4 | 1 | 30
          5 | 2 | 15

          Hier kommt eine neue Version mit der ID 5 Hinzu.

          Tabelle 2: Parameter

          Konstante_ID | Konstante
          1 | C1
          2 | C2
          3 | C3
          4 | C4

          bleibt gleich.

          Tabelle 3: Varianten

          Variante_ID | Beschreibung
          1 | Variante1
          2 | Variante2

          bleibt auch gleich.

          Tabelle 4: Verknuepfungstabelle

          Konstante_ID | Version_ID | Variante_ID
          1 | 1 | 1
          2 | 2 | 1
          3 | 3 | 1
          4 | 4 | 1
          1 | 1 | 2
          2 | 2 | 2
          3 | 3 | 2
          4 | 4 | 2
          2 | 5 | 1

          Hier wird der Konstante C2 (Konstante_ID = 2) der Variante 1 (Variante_ID = 1) jetzt zusätzlich der Wert 15 (Versions_ID = 5) zugeordnet. Es gibt also 2 Werte die der Konstanten_ID = 2 zugeordnet werden (2|2|1 und 2|5|1). Von diesen beiden soll nur der neuere Wert (2|5|1) in der Ergebnistabelle abgefragt werden.

          Ergebnistabelle für Variante 1:

          Konstante_ID | Version_ID | Version | Value

          1 | 1 | 1 | 24
          2 | 5 | 2 | 15
          3 | 3 | 1 | 20
          4 | 4 | 1 | 30

          Ausgegeben werden die 4 Konstanten der Variante 1 mit der neuen Versionsnummer und dem neuen Wert (der zweite Wert von 10, der der Konstanten C2 bei der Variante 1 zugeordnet ist wird nicht mit ausgegeben)

          Ergebnistabelle für Variante 2:

          1 | 1 | 1 | 24
          2 | 2 | 1 | 10
          3 | 3 | 1 | 20
          4 | 4 | 1 | 30

          Hier ändert sich nichts da der neue Parameter nur für Variante 1 gilt.

          Diese Versionsänderung soll zusätzlich noch in beliebiger Anzahl wiederholt werden können. Es soll also möglich sein Versionen bis X anzulegen, wobei immer nur der neueste Wert in der Ergebnistabelle abgefragt wird.


          Comment


          • #6
            Ok, habs hoffentlich verstanden. Nehmen wir Dein Statement:
            Originally posted by Froschn View Post
            ..
            Mein Code:
            Code:
            SELECT Versionen.*, Konstante
              FROM Versionen
              JOIN Verknuepfungstabelle ON Verknuepfungstabelle.Version_ID = Versionen.Version_ID
              JOIN Parameter            ON Parameter.Konstante_ID = Verknuepfungstabelle.Konstante_ID
              JOIN (SELECT Konstante_ID, MAX(Versionen.Version) AS High_Version
                      FROM Parameter, Versionen GROUPBY Konstante_ID) b ON
                                           b.Konstante_ID = Parameter.Konstante_ID
                                       AND b.High_Version = Versionen.Version
             where Variante_ID = 1
             ORDER BY Parameter.Konstante_ID DESC
            ..
            Das ist Dein Statement etwas nachbearbeitet. Funktioniert so natürlich auch nicht.

            Du machst Aggregat im Subselect b ( das wie bereits gesagt einen cross join fährt, der vermutlich gar nicht erwünscht ist)
            Was soll hier auf basis der Versions Tabelle aggregiert werden? Dir ist wahrscheinlich nicht klar, wie sich Gruppierung und Aggregatfunktion auswirken.
            Hast Du mal das Statement B für sich laufen lassen? Dein Statement sagt, gib mir für jede eindeutige Konstante_id das höchste aus Version. 4 eindeutige Werte für Konstante_id und (jeweils) das Maximum von Version. Das würde irgendwas halbwegs sinnvolles ergeben, wenn die tabellen ein Join Kriterium hätten und es bedient würde. So kommt Schrott raus.
            Kleiner Exkurs: Du schreibst so ausführlich INNER JOIN, da gibt es glaub ich Syntaxvarianten, die erlauben es, das Join Kriterium weg zu lassen. Das lautet dann glaub ich NATURAL JOIN. Ich weiß nicht, ob Dir sowas vorschwebte oder ob es einfach ein Flüchtigkeitsfehler war. Es ist jedenfalls alles für die Tonne.
            Schreib die JOIN Kriterien hin und zwar die, die Du wirklich brauchst.*

            Aber mal zum Kern: Eine Aggregation brauchst Du natürlich und Du machst sie auch. Aber auf Basis der Tabellen, die Du dafür nutzt, hast Du keine Chance, die richtigen Werte zu finden. Weder die Versionstabelle noch die Parameter liefern die Daten, um das Maximum in Bezug auf die Relationen aus den anderen Tabellen zu finden.
            Das geht nur über die Verknüpfungstabelle.

            Also versuch mal darüber, Dein Aggregat Subsulect B zu bauen.

            * Variante_ID=1 ist m.E. kein JOIN Kriterium, sondern ein Filter, deshalb habe ich es schonmal in die WHERE clause gesetzt. Du kannst ihn weglassen, ohne dass falsche Daten angezeigt würden (wenn das Statement insgesamt funktioniert) und erhälst dann einfach das uneingeschränkte Gesamtergebnis.

            Comment


            • #7
              Habs noch nicht hinbekommen aber zum Verständnis vlt. noch mal ein weiteres Beispiel.
              Habe die Ursprungstabelle Bild 1.

              Verwende den Code Bild 2.

              Und erhalte die Ergebnistabelle Bild 3.

              Jetzt möchte ich die Parameter_ID in eine neue Tabelle ziehen aber das gleiche Ergebnis bekommen.
              Attached Files

              Comment


              • #8
                MMh, also es ist nicht so einfach Dir zu helfen
                - Bilder sind hübsch, aber schlecht brauchbar für die Arbeit mit SQL Texten und Daten
                - Deine Angaben sind unklar bis kryptisch oder nichtssagend

                "Habs noch nicht hinbekommen", was soll man dazu als Hinweis geben? "Schade"?
                "In eine neue Tabelle ziehen abder das gleiche Ergebnis bekommen" ????
                Haben sich da die Anforderungen geändert?

                Bitte mache jetzt und zukünftig bei vergleichbaren Problemen einfach eine Textkopie der Statements und der Daten. Wir sind ja nicht in einem Bildbearbeitungsforum.

                Ich sehe immerhin, Du machst eine richtige Bestimmung eines Maximalwertes und einen Selfjoin auf die Originalmenge und verwendest dabei die Tabelle, die die benötigten Werte enthält.

                Was ist nun das Problem?

                Comment


                • #9
                  Danke für den Hinweis defo2.
                  Als ich es mir heute nochmal angeschaut habe, dachte ich mir auch wie soll das jemand verstehen, der nicht in der Thematik drin ist.
                  Ich denke vlt. schon zu lange über das Problem nach.

                  Also wie du schon richtig erkannt hast mache ich eine Bestimmung des Maximalwertes über einen Selfjoin

                  SELECT a.*
                  FROM Table1 a
                  JOIN (SELECT Parameter_ID, MAX(Version) as maximum
                  FROM Table1)

                  --> den Selfjoin möchte ich an dieser Stelle ändern und den Wert Parameter_ID aus einer anderen Tabelle abfragen (so ist es in der DB umgesetzt. Die Spalte Parameter_ID gibt es nicht in Table1 sondern nur in Table2). Sowas wie

                  JOIN (Select (SELECT Parameter_ID FROM Table2), max (Version) as maximum
                  FROM Table1
                  group by Parameter_ID)

                  Gibt es die Möglichkeit innerhalb der Join Funktion Werte aus anderen Tabellen über select abzufragen?

                  Comment

                  Working...
                  X