SQL Left Join mit Select Filterung und nur einem Datensatz

w2t

Newbie
Registriert
Nov. 2021
Beiträge
2
Hallo Zusammen

Ich bin neu hier und trete direkt mit einer Frage an die Experten.

Ich zerbeisse mir jetzt schon seit längerem die Tischkante an folgendem Problem:

Wir haben Artikel, die einen oder mehrere Unterartikel haben.
Die beiden Informationen sind jeweils in zwei Tabellen vorhanden.
Die eine Tabelle ist die Artikel Tabelle und die Andere die Stücklistentabelle.
Nun wollte ich beim Join der beiden Tabellen eine Filterung einfügen, was auch mit der selectierung der Tabelle gelungen ist.

Nun ist mein Problem, das ich drei Datensätze angezeigt bekomme, wenn der Artikel 3 Unterartikel hat usw. Ich will aber nur den ersten angezeigt bekommen, da die Unterartikel nur Hilfsinformationen sind.

Die Selektierung ist wie folgt:
Code:
Left JOIN (Select a.Father, a.Code from ITT1 a where a.Code like '%-009-%') T5 ON T0.ItemCode = T5.Father
Die Auswahl der Daten:
Code:
SELECT T5.Code as UBG
Kann ich da irgendwie eine Begrenzung auf den ersten Datensatz einbauen?

Vielen Dank im Voraus für die Hilfe.
Da komme ich echt an den Anschlag.

Grüsse

Timmy
 
wenn egal ist welche zeile kommt:

Code:
SELECT T5.Code as UBG FETCH FIRST 1 ROWS ONLY;
 
Hi,

LIMIT 1, DISTINCT... sowas schon getestet? Also entweder das Subselect auf ein Element limitieren oder eben auf einen Schlüssel des Elternelement distinct setzen?

VG,
Mad
 
Willkommen im Forum!

Am besten stellt man bei solchen Fragen auch Testdaten zur Verfügung. Das heißt die beteiligten Tabellen mit Beispieldaten gefüllt und idealerweise auch mit dem gewünschten Endergebnis.

Abgesehen davon solltest du auch immer angeben um welches SQL es sich handelt, weil sich die SQL-Dialekte unterscheiden. MSSQL, MySQL, Postgresql, etc. unterscheiden sich im Detail. Es kann daher durchaus sein, dass die eine oder andere Lösung, die man aus einem Forum holt, nicht passt, weil sie für einen anderen SQL-Server gedacht ist.


*edit
Ich meine zum Beispiel, dass SELECT TOP 1 bei Postgresql nicht funktioniert, wenn ich mich nicht täusche. Dort müsste man das mit LIMIT 1 lösen. Im Zweifelsfalle also alle hier genannten Lösungen ausprobieren - oder den verwendeten SQL-Server nennen ;)

**edit
MySQL kennt laut Dokumentation auch kein TOP. Das scheint weitestgehend nur MSSQL-spezifisch zu sein.
 
Zuletzt bearbeitet:
Wie schon erwähnt ist das einfachste hier vielleicht DISTINCT

SQL:
LEFT JOIN (
    SELECT DISTINCT a.Father, a.Code
    FROM ITT1 a
    WHERE a.Code LIKE '%-009-%') T5 ON T0.ItemCode = T5.Father

Das setzt aber voraus, dass es nicht mehrere verschiedene Codes pro Father gibt. Dann müsstest du dich fragen, welchen Code du pro Father brauchst.
 
Ein simples Right Join würde schon reichen.

bei Left:
t1.1 - t2.1
t1.2 - t2.1
t1.3 - t2.1

bei Right:
t1.1 - t2.1
mehr kommen dann nicht weil rechts kein weiterer DS ist.

edit: ups hier hab ich mich geirrt, das funktioniert nur wenn der Join kein Hit jeweils hat.

Wobei ich fast glaube, dass der grundlegende Ansatz nicht korrekt ist. Wenn das Subselect 3 DS liefert, wird das ja nicht ohne Grund sein. Subselects in Joins find ich zudem eh nicht prickelnd.
 
Zuletzt bearbeitet:
Deswegen sind Fragen mit vordefinierten, selbst erdachten (Teil-)Lösungen auch immer unpraktisch, weil die Gefahr besteht, ein XY-Problem zu produzieren. Eigeninitiative in allen Ehren, aber alle Antworten hier lösen nur das Y, nämlich das Beheben der Schwachstelle der Fast-Lösung des TE, obwohl man vielleicht direkt das X lösen könnte.

Hätte man Beispieldaten, Edge Cases und Kenntnis über den verwendeten SQL-Server, könnte man eventuell das zugrundeliegende SELECT bereits anders formulieren - keine Ahnung ob das hier wirklich der Fall wäre, aber ohne besagte Infos hat man nicht einmal die Chance, sowas überhaupt vorzuschlagen :(
 
  • Gefällt mir
Reaktionen: RenoV, mental.dIseASe und Madman1209
Hallo Zusammen

Wow. Vielen Dank erstmal für die ganzen Antworten.

Mein Problem ist wohl verzwickter, als ich es beschrieben habe. Die Herausforderung am ganzen ist, dass das Basis-System wo das drinn läuft SAP Business One ist. Im Prinzip ist es MS SQL und kann entsprechend auch alle darin verwendeten Befehle umsetzen. Nur das da halt debugging eher schwierig ist.

Im Prinzip ist die Funktionsweise Folgende:

Wir haben eine Tabelle mit allen Kundenaufträgen. Diese werden in einer Art Lieferliste nach Datum sortiert angezeigt. Jeder Artikel hat eine Stückliste, die oft auch eine Unterbaugruppe enthält. Die Artikelnummern bei uns sind sprechend. Das heisst, dass sie in mehrere Nummerische Blöcke aufgeteilt sind XXX-XXX-XXXX. Die Unterbaugruppen (UBG) sind mit XXX-009-XXXX gekennzeichnet. Nun soll in dieser Lieferliste die Unterbaugruppe als Hilfe mit angezeigt werden. Einzelne Ausnahmen haben 3-4 Unterbaugruppen. Diese werden mir aktuell 3 oder 4 mal ausgegeben. Da die Mitarbeiter aber nach dieser Liste ausliefern, dürfen Sie dann nicht z.B. 3 Zeilen angezeigt bekommen, weil dann die Gefahr ist, dass 3 mal ausgeliefert wird.

Nun war mein Ansatz, wenn drei UBG gefunden wurden, die Ergebnisse Komma getrennt anzuzeigen. Dies habe ich aber erst gar nicht gelöst bekommen. Dann hatte ich mich dafür entschieden, nur die erste UBG die gefunden wird anzuzeigen.

Leider darf ich euch keine Tabelleninhalte zeigen.

Aber hier ist erstmal mein ganzer Code:

Code:
SELECT T1.[CardCode], T1.[CardName], T1.[DocNum], T1.[DocEntry], T1.[NumAtCard], T0.[ItemCode], T0.[Dscription], T0.[Quantity], T0.[OpenQty], T0.[DelivrdQty], T0.[ShipDate], T0.[LegalText] AS 'Prod-Fortschritt', T0.[FreeTxt], T0.[SubCatNum], T0.[Text], (T0.[LineTotal]*1.076) AS Umsatz
 , T2.[OnHand], T4.[OnHand] as Halbfabrikat, T5.[Code] as UBG, T2.[OnOrder], T2.[IsCommited], ISNULL(T0.[U_CS_Abruf],'N') AS Abruf, (MONTH(T0.[ShipDate])) AS Monat, FORMAT(T0.[ShipDate], 'MMMM', 'de-DE') AS Monatname, (YEAR(T0.[ShipDate])) AS Jahr
FROM RDR1 T0 
INNER JOIN ORDR T1 ON T0.[DocEntry] = T1.[DocEntry]
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode
Left JOIN (Select TOP 1 a.[Father], a.[Code] from ITT1 a where a.Code like '%-009-%') T5 ON T0.ItemCode = T5.Father
Left JOIN OITM T4 ON T5.Code =  T4.ItemCode
INNER JOIN OITW T3 ON T0.[ItemCode] = T3.[ItemCode] AND T3.[WhsCode] = '01'
 WHERE T0.[OpenQty] >0 AND ISNULL(T2.U_NotLieferliste,'N') = 'N' AND  T0.[ShipDate]  <= '[%ShipDate]' AND T0.[U_CS_Abruf] = 'Y'
 ORDER BY T1.[CardName], T0.[ItemCode],T0.[ShipDate]

Sachen wie Distinct, First und Top habe ich ausprobiert. Leider hat es entweder nichts mehr ausgegeben oder einen Fehler gebracht. Entweder meine verschachtelung ist zu komplex oder ich habe die Anwendung dieser Befehle nicht verstanden.

Vielen herzlichen Dank für eure Hilfe und sorry für die Undeutliche Beschreibung.

Viele Grüsse Timmy
 
w2t schrieb:
Nun war mein Ansatz, wenn drei UBG gefunden wurden, die Ergebnisse Komma getrennt anzuzeigen. Dies habe ich aber erst gar nicht gelöst bekommen. Dann hatte ich mich dafür entschieden, nur die erste UBG die gefunden wird anzuzeigen.
Das geht (z.T. versionsabhängig) : STRING_AGG()
Kann aber bei großen Ergebnismengen entsprechend auf die Performance gehen!

Edit:
Ok... da waren Corona bedingt die Buchstaben für Tables und Views ausverkauft?
Das is ja krass.
Ich hab schon viel übles gesehen, aber das ist echt mega hart... :O
 
Zuletzt bearbeitet:
w2t schrieb:
Leider darf ich euch keine Tabelleninhalte zeigen.
Niemanden interessieren eure konkreten Produkte und Teile. Verwende einfach Beispieldaten und ersetze brisante Infos durch Äpfel, Birnen und von mir aus auch Rosinen... Eine 10-zeilige Select-Anweisung mit Subselects ist aber schwierig zu debuggen, wenn man die Datenstruktur nicht kennt - und handfeste Beispiele wie das Ergebnis aussehen soll.
 
  • Gefällt mir
Reaktionen: mental.dIseASe und Madman1209
Zurück
Oben