Unterabfragen

TizianK

Benutzer
Beiträge
16
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
 
Werbung:
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.
 
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
 
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
 
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.
 
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
 
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?
 
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!
 
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.
 
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 :)
 
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
 
Werbung:
Zurück
Oben