# MySQL LEFT OUTER JOIN mit mehreren identischen Werten rechts



## AlexTM1 (2. Mai 2019)

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


----------



## Zvoni (3. Mai 2019)

Zeig mal die SQL die du bisher hast


----------



## Kalito (3. Mai 2019)

Hallo,

um ein Subselect wirst du nicht rumkommen.


```
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 (3. Mai 2019)

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 (3. Mai 2019)

Das ist der Code vom View: 
	

		
			
		

		
	



```
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 (3. Mai 2019)

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


```
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 (3. Mai 2019)

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 (3. Mai 2019)

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 (3. Mai 2019)

Hallo Kalito,
das klingt sinnvoll. 
Für die 99% muss ich


```
WHERE dbo.Artikel.Loeschen IS NULL
```

am Ende hinzufügen.
Das eine Prozent verstehe ich aber nicht. Was muss ich hier einsetzen? 


```
DISTINCT rt.vergleich as vergleich
            ,rt.Wert1
            ,rt.Wert2
```

Vielen Dank für die Hilfe


----------



## Kalito (3. Mai 2019)

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:


```
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:


```
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.


----------



## AlexTM1 (3. Mai 2019)

Hallo Kalito, vielen Dank. In diesem Fall wie vorgeschlagen die höchste ID zu verwenden halte ich für am sinnvollsten.


----------



## Kalito (3. Mai 2019)

War mit meinen Beitrag noch nicht fertig. Hab aus versehen auf Speichern geklicke


----------



## AlexTM1 (3. Mai 2019)

müsste es bei DISTINCT nicht dbo.Artikel.Artikelnummer heißen?


----------



## AlexTM1 (3. Mai 2019)

super, vielen Dank!


----------



## Kalito (3. Mai 2019)

AlexTM1 hat gesagt.:


> müsste es bei DISTINCT nicht dbo.Artikel.Artikelnummer heißen?



NIcht unbedingt, da du nur die eine Tabelle ansprichst.


----------

