Webstatt.org - Community seit 2006 - 2012 (2024?)

Query ins Gegenteil drehen

user-343
04.08.2006 21:41

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

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)

Avatar user-255
04.08.2006 21:47

where not..?

Those who can, do. Those who can't, teach. # Musik gehört dem Volk! # last.fm
user-343
04.08.2006 21: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. user-158n 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.

Avatar user-255
04.08.2006 22:06

Ach so.. sry, hatte wohl zu sehr überflogen zwinkern

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

Those who can, do. Those who can't, teach. # Musik gehört dem Volk! # last.fm
user-343
04.08.2006 22:11

Original von user-255
Ach so.. sry, hatte wohl zu sehr überflogen zwinkern

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 zwinkern

Avatar user-255
05.08.2006 08:34

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

Ganz gut beschrieben wird die Technik hier unter "OUTER JOINs". lächeln

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.

Those who can, do. Those who can't, teach. # Musik gehört dem Volk! # last.fm
user-343
05.08.2006 11:01

Ah... Intressant. user-158ke.
Aber ganz unverändert kann ich den Query leider nicht übernehmen - so endet es in einer Fehlermeldung:
#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 user-158k für die fast richtige Lösung lächeln

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

Avatar user-255
05.08.2006 11: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 zwinkern

Those who can, do. Those who can't, teach. # Musik gehört dem Volk! # last.fm