MySQL LEFT OUTER JOIN mit mehreren identischen Werten rechts


AlexTM1

Grünschnabel
#1
Hallo zusammen,
ich bin jetzt schon ein paar Stunden am suchen, finde aber nicht die richtige Lösung.
Ich möchte die linke Tabelle mit Werten aus der rechten Tabelle anreichern.
Das klappt soweit auch mit LEFT OUTER JOIN einwandfrei. Es gibt jedoch ein paar Einträge in der rechten Tabelle, die im Vergleichsfeld identische Werte haben.

So werden mir am Ende mehr Zeilen ausgegeben, als die linke Tabelle eigentlich hat.

Ist soweit auch korrekt, nur muss ich die mehrfachen Zeilen vermeiden. Wie kann ich sicherstellen, dass exakt die gleiche Anzahl an Zeilen der linken Tabelle ausgegeben wird? Wenn bei mehreren gleichen Werten in der rechten Tabelle die erst-beste Zeile verwendet wird, ist das in Ordnung.

Vielen Dank für die Hilfe und vielen Dank an das Forum!

Alex
 

Kalito

Erfahrenes Mitglied
#3
Hallo,

um ein Subselect wirst du nicht rumkommen.

SQL:
SELECT
    *
FROM
    linke_tabelle lt
LEFT JOIN
    (
        SELECT
            DISTINCT rt.vergleich as vergleich
            ,rt.Wert1
            ,rt.Wert2
        FROM
            rechte_tabelle rt
    ) rt_sub
    ON rt_sub.vergleich = lt.vergleich
 

Zvoni

Erfahrenes Mitglied
#4
Auch ne Idee.
Wäre jetzt eher Richtung Max(RechteTabelle.MeinWert) mit einem GROUP BY auf linke Tabelle gegangen, da es ihm ja egal ist, welchen Wert er aus der rechten Tabelle bekommt.
 

AlexTM1

Grünschnabel
#5
Das ist der Code vom View: 1.jpg
SQL:
SELECT     TOP (100) PERCENT dbo.Buchungen.Datum, dbo.Vorgangstyp_Buchungen.Vorgangstyp AS Typ, dbo.Buchungen.Artikelnummer, ISNULL(dbo.Artikel.Bezeichnung, '')
                      AS Artikelname, dbo.Buchungen.Menge, ISNULL(dbo.Artikel.Einheit, '') AS Einheit, dbo.Buchungen.Lager, dbo.Buchungen.Vorgang, ISNULL(dbo.Buchungen.Mitarbeiter,
                      '') AS Mitarbeiter
FROM         dbo.Buchungen LEFT OUTER JOIN
                      dbo.Artikel ON dbo.Buchungen.Artikelnummer = dbo.Artikel.Artikelnummer INNER JOIN
                      dbo.Vorgangstyp_Buchungen ON dbo.Buchungen.Vorgangstyp = dbo.Vorgangstyp_Buchungen.ID
In der Tabelle "Artikel" gibt es mehrere Einträge mit gleicher Artikelnummer.
 

Kalito

Erfahrenes Mitglied
#6
So ich habe mal dein SQL etwas aufpoliert, damit man es besser lesen kann.

SQL:
SELECT     
    TOP (100) PERCENT dbo.Buchungen.Datum
    , dbo.Vorgangstyp_Buchungen.Vorgangstyp AS Typ
    , dbo.Buchungen.Artikelnummer
    , ISNULL(dbo.Artikel.Bezeichnung, '') AS Artikelname
    , dbo.Buchungen.Menge
    , ISNULL(dbo.Artikel.Einheit, '') AS Einheit
    , dbo.Buchungen.Lager, dbo.Buchungen.Vorgang
    , ISNULL(dbo.Buchungen.Mitarbeiter,'') AS Mitarbeiter
FROM         
    dbo.Buchungen
LEFT OUTER JOIN
    dbo.Artikel
    ON dbo.Buchungen.Artikelnummer = dbo.Artikel.Artikelnummer
INNER JOIN
    dbo.Vorgangstyp_Buchungen
    ON dbo.Buchungen.Vorgangstyp = dbo.Vorgangstyp_Buchungen.ID
Die erste Frage, die sich mir stellt, woran sich Artikel mit gleicher Artikelnummer unterscheiden. Ich sehe bei dir das Feld Artikel.Loeschen. Kann es sein, dass immer nur eine Artikelnummer das Loechen-Flag nicht gesetzt hat?

Darüber hinaus ist zu klären, ob es Buchungen gibt, wo es keinen Eintrag zur Artikelnummer gibt. Ergo könntest du anstatt eines LEFT Join auch ein INNER Join nehmen.

Gruß Patrick
 

AlexTM1

Grünschnabel
#7
Hallo Patrik,
danke für die Antwort. Im aktuellen Fall ist das löschen-Flag tatsächlich nicht gesetzt. Fällt aber leider nur dadurch auf, dass die Buchungen im View nicht stimmen. Heißt, ich kann nicht 100%ig ausschließen, dass Artikelnummer immer eindeutlig ist, wenn das löschen-Flag zur Hilfe genommen wird. Für 99% würde es wahrscheinlich reichen.
Ja, Es gibt Einträge, zu denen es (noch) keinen passenden Eintrag in der Tabelle "Artikel" gibt.


Gruß
Alex
 

Kalito

Erfahrenes Mitglied
#8
Hallo,

Mir will sich nicht so recht erschließen, warum 2 Artikel die gleiche Artikelnummer haben. wie das aktuell isr, kaufe ich ein Buch, bekomme aber eine cd, da beide die selbe Artilelnummer haben. Aber egal. gehen wir davon aus, dass wir 99% über den lösch-flag eindeutig bekommen, dann würde ich bei dem restlich 1% die höchste id nehmen.
 

AlexTM1

Grünschnabel
#9
Hallo Kalito,
das klingt sinnvoll.
Für die 99% muss ich

SQL:
WHERE dbo.Artikel.Loeschen IS NULL
am Ende hinzufügen.
Das eine Prozent verstehe ich aber nicht. Was muss ich hier einsetzen?

SQL:
DISTINCT rt.vergleich as vergleich
            ,rt.Wert1
            ,rt.Wert2
Vielen Dank für die Hilfe
 

Kalito

Erfahrenes Mitglied
#10
Hallo,

laut deiner Aussage ist das Löschkennzeichen nicht aussreichend um eine Artikel eindeutig (unique zu identifizieren). Jetzt stellt sich die Frage, ob es egal ist, welche Artikelnummer genommen wird oder ob es der erste bzw. letzte Treffer sein soll.

der erste Fall sieht so aus:

SQL:
SELECT
    *
FROM        
    dbo.Buchungen
INNER JOIN
    dbo.Vorgangstyp_Buchungen
    ON dbo.Buchungen.Vorgangstyp = dbo.Vorgangstyp_Buchungen.ID
LEFT JOIN
    (
        SELECT
            DISTINCT Artikelnummer 
            ,Bezeichnung,
            ,Einheit,
        FROM
            dbo.Artikel
       WHERE
           Loeschen IS NULL
    ) artikel
    ON artikel.Artikelnummer=  dbo.Artikelnummer.vergleich
und der zweite so:

SQL:
SELECT
    *
FROM        
    dbo.Buchungen
INNER JOIN
    dbo.Vorgangstyp_Buchungen
    ON dbo.Buchungen.Vorgangstyp = dbo.Vorgangstyp_Buchungen.ID
LEFT JOIN
    (
        SELECT
            Artikelnummer
            ,Bezeichnung,
            ,Einheit,
        FROM
            dbo.Artikel
       WHERE
           Loeschen IS NULL
          and id IN (
              SELECT
                  MAX(id)
               FROM
                   dbo.Artikel
               GROUP BY
                   Artikelnummer
          )
    ) artikel
    ON artikel.Artikelnummer=  dbo.Artikelnummer.vergleich
willst du anstatt den letzten Wert den ersten, musst du min nehmen.
 
Zuletzt bearbeitet: