Willkommen in der Webstatt Zum Webstatt Blog und Stories
Wasili am 04.08.06 23:41

Frisch aus den Ferien zurück schon das nächste, kleinere Problem ;)

In einer Datenbank sind Hausschlüssel. Nun soll dieser Query alle Schlüssel raussuchen, dessen "owner" nicht in der Datenbank "accounts" existiert. Nun, ja. Zuerst hab ich ja das da gedacht..:

$sql = 'SELECT `items`.`id`,`items`.`value2` FROM `items`
INNER JOIN `accounts`
ON `accounts`.`acctid` = `items`.`owner`
WHERE `class` = "Schlüssel"
AND `value1` = "'.$session['user']['house'].'"
ORDER BY `id` ASC';


Aber nach dem ausprobieren musste ich merken, dass es das genaue Gegenteil bringt. Es listet die Schlüssel auf, die jemandem gehören. Nicht aber die, die niemandem gehören.
Weiss wer, wie ich es verdrehen kann?
Dass der Query einen Datensatz liefiert mit den Schlüsseln, dessen "owner" mit keinem Datensatz in der Tabelle "accounts" überreinstimmt?
(owner === acctid)

netcup.de Warum gibt es hier Werbung?
milahu milahu am 04.08.06 23:47

where not..?

Wasili am 04.08.06 23:53

Mh? Where not?
Wenn du dies nun als Baustein für den Query meinst:
Naja. Die Where-Klausel stimmt so ja. "class" muss "Schlüssel" sein, "value1" muss den Wert der Variabel haben. Das stimmt.
Das einzige ist diese Zeile hier:
ON `accounts`.`acctid` = `items`.`owner`

Einfach ein != hinmachen bringt ja nix. Dann sieht es so aus:
http://www.legend-of-vinestra.de/schluessel3.jpg

Eventuell zur Veranschaulichung des ersten Querys:
http://www.legend-of-vinestra.de/schluessel1.jpg
Nur brauch ich die Nummern 8,9 und 12, dann das sind die, die "verloren" gegangen sind.

milahu milahu am 05.08.06 00:06

Ach so.. sry, hatte wohl zu sehr überflogen ;)

Aber wenn das item keinen owner hat, sollte das doch in der Datenbank gespeichert
sein, oder? Sprich, dass das owner Feld dann auf Null steht.

Dann einfach
> select * from items where owner = null

Wasili am 05.08.06 00:11

Quote
Original von milahu
Ach so.. sry, hatte wohl zu sehr überflogen ;)

Aber wenn das item keinen owner hat, sollte das doch in der Datenbank gespeichert
sein, oder? Sprich, dass das owner Feld dann auf Null steht.

Dann einfach
> select * from items where owner = null


Theoretisch, ja. Wenn der Account Ordnungsgemäss gelöscht wird, ist das auch so. Nur hat es wohl mehr irgendwo eine Löschmöglichkeiten, die das ausser Acht lassen. Somit irren in der Datenbank Schlüssel umher, die halt "verloren" sind.

Um das "Verloren"-sein nochmal zu erklären:
Ein Schlüssel ist dann verloren, wenn der Wert in der Spalte "owner" nicht in der Tabelle "accounts" zu finden ist.
Eine Mehr-Query-Möglichkeit hab ich ja. Zuerst alle schlüssel zum Haus holen und dann, Datensatz für Datensatz kontrollieren, ob owner in der Tabelle "accounts" ist.

Aber ich wollte es in einen Query bringen... Wenn mir jemand sagt, dass es unmöglich ist, ist auch gut ^^"

EDIT: Macht doch nichts... Wir überfliegen alle mal etwas zu schnell ;)

milahu milahu am 05.08.06 10:34

Ein bisschen gegoogelt, ein bisschen gelesen,
um dir sagen zu können, dass das mit outer join geht ;)

Ganz gut beschrieben wird die Technik hier unter "OUTER JOINs". :)

Deine Anfrage sollte dann in etwa so aussehen:
$sql = 'SELECT
i.`id`,i.`value2`
FROM
`items` as i
LEFT OUTER JOIN
`accounts` as a
WHERE
i.`class` = "Schlüssel"
AND i.`value1` = "'.$session['user']['house'].'"
AND a.`acctid` = i.`owner`
AND a.`acctid` IS NULL
ORDER BY i.`id` ASC';


Dabei werden beide Tabellen gejoint, ohne Rücksicht darauf zu nehmen, ob der passende
Datensatz in accounts existiert. Ist dem nicht so, werden einfach NULL Werte angehängt.

Wasili am 05.08.06 13:01

Ah... Intressant. Danke.
Aber ganz unverändert kann ich den Query leider nicht übernehmen - so endet es in einer Fehlermeldung:

Quote
#1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE i.`class` = "Schlüssel" AND i.`value1` = "1" AND a.`a


Ein wenig rumprobieren hat nun endlich das Ergebnis gebracht, das ich wollte:

SELECT
i.`id`,i.`value2`
FROM
`items` as i
LEFT OUTER JOIN
`accounts` as a
ON
a.`acctid` = i.`owner`
WHERE
i.`class` = "Schlüssel"
AND i.`value1` = "1"
AND a.acctid IS NULL
ORDER BY i.`id` ASC


Vielen Dank für die fast richtige Lösung :)

Noch eine letzte Frage: Die Fehlermeldung... Liegt das an der MySQL-Version (MySQL 4.0.15)?

milahu milahu am 05.08.06 13:15

> Die Fehlermeldung... Liegt das an der MySQL-Version (MySQL 4.0.15)?

Ne.. ne.. ich hab die join Bedingung zu where statt zu on gesteckt -- darum ;)

Creative Commons Lizenzvertrag
Alle Inhalte des Webstatt-Archivs stehen unter einer Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Unported Lizenz.

Impressum & Kontakt