# Komplexe SQL-Abfrage mit Inner-Joins



## Verena22 (30. Jun 2008)

Hallo allerseits!
Ich will gerade um eine Information (Auftragsnummer) zu bekommen über zwei bzw. drei Tabellen verbinden. Der Fall stellt sich wie folgt dar:

Unser Startpunkt ist die Rechnung. Von dort aus kommen wir zum Lieferschein, wenn der Basistyp 15 ist, oder wir kommen auf den Auftrag, wenn der Basistyp 17 ist. Die Basis bildet hier entweder der Lieferschein oder der Auftrag.

Liegt uns ein Lieferschein vor, kommen wir von dort aus auf den Auftrag.

Klingt einfach oder? Verbunden sind die Dokumente über Dok-IDs. 

So meine Frage, wie bilde ich für den Fall jetzt mit Inner-Joins und Where Bedingungen mein SQL-Statement dafür? Mir fällt das gerade ein bisschen schwer, weil ich mir nicht vorstellen kann, wie ich die zwei Fälle, also entweder auf den Lieferschein zu gehen oder direkt auf den Auftrag, abdecke?

Kann mir da jemand Pfiffiges weiterhelfen?

Gruß
Verena


----------



## Niki (30. Jun 2008)

Ich bin mir jetzt nicht so sicher ob ein UNION in allen DBs unterstützt wird. Aber falls es bei dir möglich ist könntest du beide Fälle unabhängig von einander damit abdecken. Das würde dann so aussehen:

```
SELECT a.auftragsnummer
FROM auftraege a, rechnung r,...
WHERE r.typ = 15,....
UNION
SELECT l.auftragsnummer
FROM lieferscheine l, rechnung r,...
where r.typ = 17
```

Ansonsten könnte es noch etwas komplizierter mit sub-Selects gehen.


----------



## Verena22 (30. Jun 2008)

Vielen Dank für die schnelle Antwort!

Wie würde man denn da Subselects bilden?


----------



## foobar (30. Jun 2008)

> Wie würde man denn da Subselects bilden?


Das ist unabhängi vom Union. 

Mit einem Union kannst du 2 Queries zu einer Verknüpfen solange die Anzahl der Spalten in beiden Queries übereinstimmt. D.h. du setzt 2 Queries ab bekommst aber nur ein Ergebnis und daher auch nur ein ResultSet.


----------



## Niki (30. Jun 2008)

Mit subselects könnte das ganze ca. so aussehen. Ich bin nicht so der SQL Profi, ich komm zwar mit meinem Wissen immer ans Ziel, aber wie performant die Statements sind kann ich nicht genau sagen.


```
select distinct a.*
from artikel a
where a.nummer in (select a2.nummer from artikel a2, lieferschein l where a2.nummer = l2.artikel and...) OR
a.nummer in (select a2.nummer from artikel a2, rechnung r where a2.nummer = .....)
```

Wie gesagt, ich würd da eher auf UNION setzen. Ist wahrscheinlich auch schneller und sicher einfacher zu lesen.


----------



## Verena22 (30. Jun 2008)

So, das mit Union hat mich schon weiter gebracht. vielen dank dafür. jetzt müsste ich nur noch folgende zwei Abfragen zusammenführen. Wäre total klasse, wenn mir auch da helfen könntet.

1) 
	
	
	
	





```
SELECT  T1.CardName, T3.Street, T3.City, T3.ZipCode, T4.Name, T1.DocNum, T1.DocDate, T2.U_hst_num,  T0.ItemCode, T0.Dscription, T0.Quantity, T0.Price, T0.LineTotal, T0.Quantity as 'Lizenzen', ORDR.Docnum 
FROM INV1 T0  
INNER JOIN OINV T1 ON T0.DocEntry = T1.DocEntry 
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode 
INNER JOIN CRD1 T3 ON T1.CardCode = T3.CardCode 
INNER JOIN OCRY T4 ON T3.Country = T4.Code 
WHERE T2.FirmCode = 9 AND T3.Address = 'Empfänger'
```

2) 
	
	
	
	





```
SELECT ORDR.Docnum
FROM ORDR, INV1
WHERE ORDR.DocEntry = (
	SELECT DLN1.BaseEntry 
	FROM DLN1 
	WHERE DLN1.DocEntry = 14388
) AND (
	SELECT INV1.BaseType 
	FROM INV1 
	WHERE INV1.DocEntry = 14338) = 15
UNION
SELECT ORDR.Docnum
FROM ORDR
where ORDR.DocEntry =  (
		SELECT INV1.BaseEntry
		FROM INV1 
		WHERE INV1.DocEntry = 14338
)AND (	SELECT INV1.BaseType 
		FROM INV1 
		WHERE INV1.DocEntry = 14338) = 17
```

Gruß
Verena


----------



## Verena22 (30. Jun 2008)

So, ich habe mich schon so weit vorgehangelt:


```
SELECT ORDR.Docnum, T0.DocEntry
FROM ORDR, INV1 T0  
INNER JOIN OINV T1 ON T0.DocEntry = T1.DocEntry 
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode 
INNER JOIN CRD1 T3 ON T1.CardCode = T3.CardCode 
INNER JOIN OCRY T4 ON T3.Country = T4.Code 
WHERE ORDR.DocEntry = (
	SELECT DLN1.BaseEntry 
	FROM DLN1 
	WHERE DLN1.DocEntry = T0.BaseEntry
) AND T0.BaseType = 15
UNION
SELECT ORDR.Docnum, T0.DocEntry
FROM ORDR, INV1 T0
INNER JOIN OINV T1 ON T0.DocEntry = T1.DocEntry 
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode 
INNER JOIN CRD1 T3 ON T1.CardCode = T3.CardCode 
INNER JOIN OCRY T4 ON T3.Country = T4.Code 
where ORDR.DocEntry = T0.BaseEntry
AND T0.BaseType = 17
```

Leider bekomme ich nur jetzt folgende Fehlermeldung vom Microsoft SQL 2005 Server:
"Meldung 512, Ebene 16, Status 1, Zeile 1
Die Unterabfrage gab mehr als einen Wert zurück. Das ist ungültig, wenn die Unterabfrage auf =, !=, <, <= , >, >= folgt oder als Ausdruck verwendet wird."

Die letzte Änderung, die ich getan habe, war im Abschnitt 

```
SELECT DLN1.BaseEntry 
FROM DLN1 
WHERE DLN1.DocEntry = T0.BaseEntry
```

Da stand anstatt von T0.BaseEntry ein fester Wert drin, den ich zum Testen genutzt habe.

Gruß
Verena
[/code]


----------



## foobar (1. Jul 2008)

Entweder du sorgst dafür, daß die Subquery nur eine Tupel liefert oder du machst das so:


```
SELECT ORDR.Docnum, T0.DocEntry
FROM ORDR, INV1 T0 
INNER JOIN OINV T1 ON T0.DocEntry = T1.DocEntry
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode
INNER JOIN CRD1 T3 ON T1.CardCode = T3.CardCode
INNER JOIN OCRY T4 ON T3.Country = T4.Code
WHERE ORDR.DocEntry in (
   SELECT DLN1.BaseEntry
   FROM DLN1
   WHERE DLN1.DocEntry = T0.BaseEntry
) AND T0.BaseType = 15
UNION
SELECT ORDR.Docnum, T0.DocEntry
FROM ORDR, INV1 T0
INNER JOIN OINV T1 ON T0.DocEntry = T1.DocEntry
INNER JOIN OITM T2 ON T0.ItemCode = T2.ItemCode
INNER JOIN CRD1 T3 ON T1.CardCode = T3.CardCode
INNER JOIN OCRY T4 ON T3.Country = T4.Code
where ORDR.DocEntry = T0.BaseEntry
AND T0.BaseType = 17
```


----------



## FenchelT (1. Jul 2008)

Verena22 hat gesagt.:
			
		

> So, ich habe mich schon so weit vorgehangelt:
> 
> 
> ```
> ...




Hallo Verena,

ist es eigentlich beabsichtigt, aus den Tabellen ORDR und INV1 zu selektieren, ohne diese miteinander in Bezug zu setzen?


Gruesse


----------



## Verena22 (1. Jul 2008)

FenchelT hat gesagt.:
			
		

> Verena22 hat gesagt.:
> 
> 
> 
> ...



Ich glaube das ist ein entscheidender Tipp gewesen 
Danke!

Jetzt muss ich nur noch mal die Daten überprüfen und wenn die stimmen, hab ich wohl die Lösung


----------

