# NULL-data processing.



## Guest (30. Aug 2004)

Hi,

weiss jemand von Euch, ob folgendes Verhalten "normal" ist oder nicht
bzw. ob es ein Standardverhalten ist?

Es gibt zwei Tabellen (TabA und TabB) mit jeweils einer Spalte, nennen wir sie 
mal strField.

TabA.strField
TabB.strField

Vergleicht man zwei Zeilen, die NULL sind, miteinander (in einem Join etc.), 
dann liefert die Bedingung FALSE bzw. keine Datensätze zurück.

```
FROM Tabelle1 TabA, Tabelle2 TabB
WHERE ...
    AND TabA.strField = TabB.strField
```

Prüft man, ob beide NULL sind, dann ist das Ergebnis TRUE bzw. es werden paar
Datensätze zurückgegeben.


```
FROM Tabelle1 TabA, Tabelle2 TabB
WHERE ...
  AND TabA.strField IS NULL 
  AND TabB.strField IS NULL
```

Ist es bei allen Datenbanken so? Ich verwende SAPDB.
Nach meinem Verständnis sollte NULL = NULL immer TRUE sein.


----------



## Guest (30. Aug 2004)

Übrigens, Abhilfe schafft hier folgendes.

```
WHERE ...
  AND (
    (TabA.strField = TabB.strField) 
    OR (TabA.strField IS NULL AND TabB.strField IS NULL)
  )
```
Warum ein direkter Vergleich zweier NULL-Werte nicht möglich
ist, ist mir aber ein Rätsel.


----------



## foobar (30. Aug 2004)

```
FROM Tabelle1 TabA, Tabelle2 TabB
WHERE ...
    AND TabA.strField = TabB.strField
```
In diesem Fall machst du einen Join über 2 Tabellen, das heißt beide Tabellen werden, anhand der Whereklausel, miteinander verknüpft und die Ergebnismenge wird zurück geliefert.


```
FROM Tabelle1 TabA, Tabelle2 TabB
WHERE ...
  AND TabA.strField IS NULL 
  AND TabB.strField IS NULL
```
Hier erstellst du ein Kreuzprodukt. Das bedeutet die beiden Tabellen werden ohne eine Bedingung miteinander verknüpft. Da du in der Whereklausel auf null prüfst bekommst du alle Datensätze bei denen diese Bedingung zutrifft.

P.S. SQL ist keine imperative sondern eine deklarative Sprache. Das bedeutet du definierst eine Ergebnismenge, anstatt einen konkreten Lösungsweg vorzugeben.


----------



## foobar (30. Aug 2004)

> Warum ein direkter Vergleich zweier NULL-Werte nicht möglich
> ist, ist mir aber ein Rätsel.


Was genau willst du denn machen?


----------



## Guest (30. Aug 2004)

foobar hat gesagt.:
			
		

> Was genau willst du denn machen?


Die Zeilen zweier "fast" gleicher Tabellen holen, die in bestimmten
Spalten übereinstimmen.
z.B.
Angenommen in Tabelle TabA steht folgendes
a=1, b=2, c=NULL, ...
In Tabelle TabB dann genau das gleiche
a=1, b=2, c=NULL, ...

```
WHERE TabA.a = TabB.a
  AND TabA.b = TabB.b
  AND TabA.c = TabB.c
```
sollte dann die Zeile mit den Spalten aus beiden Tabellen liefern.
Ist aber nicht der Fall, sobald ein Spaltenpaar NULL ist.
Für den Fall, wo sowas möglich ist, muss man immer diese
"komplizierten" Bedingungen schreiben.
Im obigen Fall

```
WHERE TabA.a = TabB.a
  AND TabA.b = TabB.b
  AND ((TabA.c = TabB.c) OR (TabA.c IS NULL AND TabB.c IS NULL))
```

Hat mich heute etwas Zeit mit dem Debugger gekostet,
dann habe ich die Abfragen erneut geprüft und bin auf
dieses Verhalten gestossen.


----------



## foobar (30. Aug 2004)

Dann mußt du einen Left-Join machen:

```
Select *
from taba a left join tabb b on (a.a = b.a)
where a.b = b.b
```
Dann bekommst du auch Datensätze in denen nulls in der zweiten Tabelle sind.


----------



## Guest (30. Aug 2004)

Nein, es liefert auch falsche Ergebnisse.

Es sind zwei, von der Struktur her, gleiche Tabellen.
Die eine ist einer Art Template-Tabelle, die andere
enthält vom Benutzer modifizierte Daten, die 
ursprünglich aus der globalen Vorlage kommen.
Der Wert der Spalte, die NULL enthalten kann, hat eine
spezielle Bedeutung. NULL = überall gültig, sonst abhängig
vom Benutzer.
Jetzt soll der Anwender die Möglichkeit haben, die modifizierten
Einträge in seiner lokalen Tabelle mit denen aus der globalen 
Tabelle abzugleichen, wenn sich diese von der lokalen in 
irgendeiner Form unterscheiden.
Das ganze läuft teilweise interaktiv, so dass ich zuerst alle
potentiellen Kandidaten für den Abgleich finden muss.
Es gibt dann zusätzlich Einträge, die der Anwender als "readonly"
gekennzeichnet hat. Diese sollen dann ignoriert bzw. nicht 
upgedated werden. 

Wenn's nicht genug wäre, es gibt da noch untergeordnete Tabellen, 
die bei dem Vergleich auch eine Rolle spielen. *amocklauf*


----------



## foobar (30. Aug 2004)

Aber das würde dann ja bedeuten, daß jeder Benutzer eine eigene Tabelle hat. Was wiederum bedeutet, daß wenn du einen Benutzer anlegst du auch eine Tabelle anlegen mußt. Warum machst du nicht eine Tabelle für die Userdaten mit einer Spalte, die dann einen Benutzer referenziert? Was soll denn Ziel des ganzen sein?


----------



## Guest (30. Aug 2004)

Es sind zwei Tabellen.

Die Tabelle mit den Anwender-spezifischen Modifikationen
hat einen eindeutigen Verweis (FK) auf den entsprechenden 
Anwender. Es ist nicht pro Anwender eine Tabelle. Solche 
Schweinereien mach' ich nicht 
Eigentlich wäre es auch möglich alles in eine Tabelle zu packen, 
lässt sich aber in zwei getrennten Tabellen besser verwalten.
Da sind auch unterschiedliche Leute für die Datenbankpflege zuständig.
Nicht jeder darf an den globalen Daten herumfummeln.

Wie ich schon schrieb, das hier funktioniert (auch bei den NULL-Spalten)

```
WHERE TabA.a = TabB.a 
  AND TabA.b = TabB.b 
  AND ((TabA.c = TabB.c) OR (TabA.c IS NULL AND TabB.c IS NULL))
```
Soll einfach heissen. Beide gleich oder beide NULL.

Aber wenn beide NULL sind, dann sind sie auch gleich.

OK das ganze wird langsam zu philosofisch


----------



## foobar (30. Aug 2004)

Wenn du in beiden Spalten Null-Werte hast brauchst du einen Full Left Join, damit bekommst du alle Daten egal in welcher der Tabellen nulls enthalten sind. Ich weiß aber nicht ob es diesen Join bei SAPDB gibt.


----------



## Guest (30. Aug 2004)

Ja, FULL JOIN wird in SAPDB auch unterstützt, ist aber grauenhaft langsam,
wenn die Tabellen viele Daten enthalten 

Habe etwas mit der Join-Syntax experimentiert. 
LEFT JOIN tut's auch und ist schnell genug.

```
SELECT ...
FROM Tabelle1 TabA LEFT JOIN Tabelle2 TabB ON (TabB.a = TabA.a AND TabB.b = TabA.b AND TabB.c = TabA.c)
WHERE TabA.userId = ... weitere Bedingungen
```

Danke. Deine Antworten haben meine grauen Zellen etwas aufgeweckt


----------



## Guest (30. Aug 2004)

Ehmmm... war quatsch. Habe bei dem Ergebnis nicht richtig hingeschaut.
Ich brauche doch die Daten aus beiden Tabellen. 

Es bleibt bei der Variante:

```
WHERE TabA.a = TabB.a 
  AND TabA.b = TabB.b 
  AND ((TabA.c = TabB.c) OR (TabA.c IS NULL AND TabB.c IS NULL))
```


----------

