Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Unterabfragen

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von TizianK, 10 Juli 2017.

  1. TizianK

    TizianK Benutzer

    Hallo,

    ich würde gerne lernen, wie ich in eine SQL Abfrage eine "Unterabfrage" einbaue und diese dann im weiteren Verlauf der Abfrage benutzen kann.
    So etwas wie eine "temporäre Tabelle" meine ich, die ich dann nur in dieser Abfrage benutzen kann.
    Sofern das möglich ist, würde mich auch interessieren, ob man diese dann benennen kann (z.B. als "t") und dann im Verlaufe der Abfrage als "t" verwenden kann.

    Danke für eure Hilfe und liebe Grüße,
    Tizian
     
  2. akretschmer

    akretschmer Datenbank-Guru

    das geht z.B. mit WITH:

    Code:
    with t as (select ...) select ... from t
    
    Ohne genau zu wissen, welches Problem Du lösen willst ist es aber schwer, Dir genauer zu helfen.
     
  3. ukulele

    ukulele Datenbank-Guru

    Es ginge auch noch als Subselect
    Code:
    SELECT t.* FROM ( SELECT ... ) t
    Oder mit einer Sicht.
     
  4. TizianK

    TizianK Benutzer

    Ich habe mehrere Tabellen. Die benötigten Tabellen sind KHKArtikel a, KHKVKBelege b und KHKVKBelegePositionen bp.
    Ich benötige aus a Matchcode, Bezeichnung1, Bezeichnung2 und die Artikelnummer. Aus b benötige ich das Belegdatum für jeden Artikel aus a (allerdings nur das aktuellste Belegdatum pro Artikel, alle älteren sollen nicht angezeigt werden).
    a und b können nicht direkt gejoined werden, da es keine Referenz gibt. Dafür brauchen wir bp. bp kann mit b durch die BelID gejoined werden und a kann wiederum mit bp durch die Artikelnummer gejoined werden.

    Ich war bisher nicht in der Lage das richtig umzusetzen, denke aber, dass eventuell eine Unterabfrage helfen kann.

    Vielleicht geht es auch ohne eine Unterabfrage.

    Lieben Gruß,
    Tizian
     
  5. TizianK

    TizianK Benutzer

    Im Moment habe ich das hier erarbeitet (geht bestimmt auch ohne Unterabfrage):

    Code:
    SELECT a.artikelnummer, a.matchcode, a.bezeichnung1, a.bezeichnung2, md.[Letzter VK]
    FROM
    (
        SELECT MAX(b.Belegdatum) AS 'Letzter VK', b.BelID, b.Mandant
        FROM KHKVKBelege b
        GROUP BY b.BelID, b.Mandant
    ) md
    INNER JOIN KHKVKBelegePositionen bp ON md.BelID = bp.BelID AND md.Mandant = bp.Mandant
    INNER JOIN KHKArtikel a ON bp.Artikelnummer = a.Artikelnummer AND a.Mandant = bp.Mandant
    ORDER BY a.artikelnummer, [Letzter VK] DESC
    Mir fehlt jetzt noch die Möglichkeit die Ausgabe der Belegdaten auf jeweils den maximalen Wert zu begrenzen und nicht alle Belegdaten auszugeben.

    Lieber Gruß,
    Tizian
     
  6. ukulele

    ukulele Datenbank-Guru

    Da gibt es mehrere Wege, deiner ist schon ganz gut. Du müsstest du mit einem erneuten Join von KHKVKBelege die Daten dazu holen:
    Code:
    INNER JOIN KHKVKBelege b2 ON md.BelID = b2.BelID AND md.Mandant = b2.Mandant AND
    md.[Letzter VK] = b2.Belegdatum
    Hat allerdings eine Unschärfe. Gibt es mehr als einen Beleg mit dem max(Datum) dann werden auch nach wie vor Zeilen doppelt zurück gegeben. Ich arbeite daher immer gerne mit ROW_NUMBER():
    Code:
    WITH t AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY b.Mandant ORDER BY b.Belegdatum) AS zeile,
    a.artikelnummer, a.matchcode, a.bezeichnung1, a.bezeichnung2, b.Belegdatum
    FROM KHKVKBelege b
    INNER JOIN KHKVKBelegePositionen bp ON b.BelID = bp.BelID AND b.Mandant = bp.Mandant
    INNER JOIN KHKArtikel a ON bp.Artikelnummer = a.Artikelnummer AND a.Mandant = bp.Mandant
         )
    SELECT *
    FROM t
    WHERE t.zeile = 1
    ORDER BY t.artikelnummer, t.Belegdatum DESC
    Ich bin mir allerdings nicht sicher was die BelID in dem Code angeht. Eine BelID kann immer nur ein Belegdatum haben oder? Das wäre dann nämlich bisher schon falsch gewesen.
     
  7. TizianK

    TizianK Benutzer

    Hallo Ukulele,

    Meine Lösung ist leider nicht gut, ich bekomme für jeden Artikel jedes Belegdatum. Ich möchte aber ja nur das aktuellste Belegdatum pro Artikel.

    Schaut euch mal dieses Bild an!

    In deiner Lösung bekomme ich zwar das aktuellste Belegdatum, allerdings nur für einen einzigen Artikel.

    Schaut euch mal dieses Bild an!

    Ich bin mir leider nicht ganz sicher woran es liegt, bzw. wie ich das gewünscht Ergebnis erzeugen kann.

    Um auf die Frage mit der BelID einzugehen:
    Ja, jede BelID kann nur ein Belegdatum haben. Ich habe im folgenden Screenshot mal das Belegdatum von ganz weit hinten herangeholt und in den Screen eingefügt, weil die Tabelle sonst viel zu breit wäre.

    Schaut euch mal dieses Bild an!

    Ich hoffe, dass du mir weiterhelfen kannst.

    Liebe Grüße,
    Tizian
     
  8. ukulele

    ukulele Datenbank-Guru

    Was kommt denn hier raus?
    Code:
    SELECT ROW_NUMBER() OVER (PARTITION BY b.Mandant ORDER BY b.Belegdatum) AS zeile,b.Mandant,
    a.artikelnummer, a.matchcode, a.bezeichnung1, a.bezeichnung2, b.Belegdatum
    FROM KHKVKBelege b
    INNER JOIN KHKVKBelegePositionen bp ON b.BelID = bp.BelID AND b.Mandant = bp.Mandant
    INNER JOIN KHKArtikel a ON bp.Artikelnummer = a.Artikelnummer AND a.Mandant = bp.Mandant
    Er sollte eigentlich durchnummerieren und bei jedem neuen Mandant wieder mit 1 anfangen. Ist b.Mandant vielleicht NULL oder so?
     
  9. TizianK

    TizianK Benutzer

    Hmm, also das Ergebnis der Abfrage sieht dann so aus:

    www.directupload.net/file/d/4781/2kxi96d5_jpg.htm

    Ich dachte auf den ersten Blick, dass das Ergebnis korrekt sei. Füge ich allerdings wieder
    Code:
    ORDER BY a.artikelnummer
    am Schluss an, kommt wieder ein unbefriedigendes Ergebnis heraus:

    www.directupload.net/file/d/4781/i6ouisyb_jpg.html

    Das bedeutet für mich, dass das obere Ergebnis auch nicht korrekt ist und ich lediglich dachte es sei korrekt aufgrund der Sortierung nach "zeile" und damit die gleichen Artikel nicht untereinander stehen.

    Edit: b.mandant = 123

    Schaut euch mal dieses Bild an!
     
  10. ukulele

    ukulele Datenbank-Guru

    Also der Code macht folgendes: Er generiert eine Zeilennummer die Zeilen des selben Mandanten (PARTITION BY) durchnummeriert und zwar in der Reihenfolge (ORDER BY) Belegdatum.

    Mir ist nicht ganz klar was du erreichen willst, vielleicht beschreibst du das nochmal.
     
  11. TizianK

    TizianK Benutzer

    Okay. Wahrscheinlich habe ich es nicht ganz korrekt erklärt.

    Beispiel:

    Wir haben zwei Artikel. Jede Artikelnummer darf im Ergebnis nur 1 Mal vorkommen und zwar genau der Datensatz mit dem aktuellsten Belegdatum.
    Ich gehe mal nur auf die zwei wichtigen Daten ein, nämlich Belegdatum und Artikelnummer.

    Artikel 1
    Artikelnummer: 123456789
    Belegdaten zu dieser Artikelnummer in KHKVKBelege: 01.07.2010; 01.10.2012; 01.08.2015

    Artikel 2
    Artikelnummer: 987654321
    Belegdaten zu dieser Artikelnummer in KHKVKBelege: 15.07.2000; 15.10.2010; 15.10.2016

    Das Ergebnis meiner Abfrage sollte dann wie folgt aussehen:
    Code:
    Artikelnummer      Letzter VK (aktuellstes Belegdatum)
    123456789          01.08.2015
    987654321          15.10.2016
    Ich hoffe, dass ich es diesmal geschafft habe, mich verständlich auszudrücken :)
     
  12. ukulele

    ukulele Datenbank-Guru

    Okay also spielt Mandant eigentlich gar keine Rolle, dann müsste das so laufen:
    Code:
    WITH t AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY a.artikelnummer ORDER BY b.Belegdatum DESC) AS zeile,
    a.artikelnummer, a.matchcode, a.bezeichnung1, a.bezeichnung2, b.Belegdatum
    FROM KHKVKBelege b
    INNER JOIN KHKVKBelegePositionen bp ON b.BelID = bp.BelID AND b.Mandant = bp.Mandant
    INNER JOIN KHKArtikel a ON bp.Artikelnummer = a.Artikelnummer AND a.Mandant = bp.Mandant
      )
    SELECT *
    FROM t
    WHERE t.zeile = 1
    ORDER BY t.artikelnummer, t.Belegdatum DESC
     
  13. TizianK

    TizianK Benutzer

    Super, vielen vielen Dank.

    Das Ergebnis sieht gut aus:

    Schaut euch mal dieses Bild an!

    Ich werd mich jetzt noch dransetzen, um die Syntax "WITH t AS" und "SELECT ROW_Number() OVER (PARTITION BY...)" vollständig zu verstehen.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden