MySql auf existierenden Eintrag prüfen

Thomasio

Erfahrenes Mitglied
Ich suche die schnellste Möglichkeit aus MySql einen Datensatz zu laden, aber nur, wenn es nur genau einen passenden Datensatz gibt.

Meine umständliche Version sieht so aus:

Code:
$abfrage = mysql_query("SELECT * FROM `tabelle` WHERE `feld1` = 'irgendwas' AND `feld2` = 'sonstwas'");
while($row = mysql_fetch_object($abfrage))
{
     $datensaetze[] = $row;
}

if(count($datensaetze) < 1)
{
     // nicht gefunden
}

if(count($datensaetze) > 1)
{
     // mehrere gefunden
}

if(count($datensaetze) == 1)
{
     $ergebnis = $datensaetze[0];
}

Wie mache ich das besser?
 
Du kannst da mit HAVING und GROUP BY arbeiten:
SQL:
SELECT *, COUNT(`feld1`) FROM `tabelle` WHERE `feld1` = 'irgendwas' AND `feld2` = 'sonstwas' GROUP BY `feld1` HAVING COUNT(`feld1`) = 1
 
Das * ist ganz unschön und gefährlich bei einem GROUP BY

MySQL ist da etwas unseriös, da du nicht alle Felder im GROUP BY definieren musst, die Gruppiert werden. Mit dem * im SELECT gruppiert er alles was nicht mit einer Guppierungsfunktion versehen ist (Also SUM(), COUNT(), MAX() etc)

Nemen wir mal diese Tabelle
Code:
my_table:
id | feld1 | feld2 | feld13
---------------------------
 1 | A     | v     | 111
 2 | A     | v     | 222
 3 | B     | x     | 333
 4 | C     | y     | 444
 5 | C     | z     | 444
Wenn man jetzt ein GROUP BY feld1 macht und dabei ein * im SELECT hat, wird trotzdem nach allen Feldern Gruppiert. Ergo wird COUNT() immer 1 ausagebn, da die id und das feld3 immer unterschiedlich ist.

Interessiert uns nur das feld1, dann kann man das simple machen, fast so wie crack gezeigt hat. Einfach den * entfernen

Das folgende Query gibt nix aus, da die Kombnation A/z 2 mal vorkommt.
SQL:
 SELECT
 	feld1
 FROM
 	my_table
 WHERE
 	feld1 = 'A'
 	AND feld2 = 'v'
 GROUP BY
 	feld1
 HAVING
 	COUNT(*) = 1;
Wird der Filter hingegen auf C/y gesetzt, dann wird auch 'C' ausgegeben, da diese Kombination nur einmal vorkommt.

Will man nun aber alle Felder von der Tabelle haben, dann kann man sie zurückverknüpfen
SQL:
SELECT
	my_data.*
FROM
	my_table AS my_data
	INNER JOIN (
			SELECT
				feld1
			FROM
				my_table
			WHERE
				feld1 = 'A'
				AND feld2 = 'v'
			GROUP BY
				feld1
			HAVING
				COUNT(*) = 1
		) AS filter
		ON my_data.feld1 = filter.feld1
		AND my_data.fedl2 = filter.feld2;

Wobei es auch hier besser wäre, den * durch eine Felderliste zu ersetzen.

Wenn du das ganze noch lesbar im PHP habe willst, dann empfehle ich die folgenden 2 Punkte
a) den SQL-Teil in PHP formatieren: Heredoc-Syntax
b) Die Complex (Curly) Syntax anwenden um die Strings zusammenzusetzen. Das reduziert das Chaos mit öffnenden und schliessenden Anführungszeichen und den Verbindungs-Punkten

PHP:
$feld1 = 'C';
$feld2 = 'y';

$sql = <<<SQL
SELECT
	my_data.*
FROM
	my_table AS my_data
	INNER JOIN (
			SELECT
				feld1
			FROM
				my_table
			WHERE
				feld1 = '{$feld1}'
				AND feld2 = '$feld2'
			GROUP BY
				feld1
			HAVING
				COUNT(*) = 1
		) AS filter
		ON my_data.feld1 = filter.feld1
		AND my_data.fedl2 = filter.feld2;
SQL;

$result = mysql_query($sql);
 
Zuletzt bearbeitet von einem Moderator:
Irgendwie hilft mir das nicht wirklich.
Ich will gar nicht alle einmaligen Datensätze haben, ich will nur dann genau einen Datensatz laden, wenn es wirklich nur einen passenden Datensatz gibt.
Wenn nicht, will ich wissen, ob es gar keinen oder mehr als einen gab, aber in dem Fall brauche ich die Daten daraus nicht.
Meine Lösung dazu funktioniert schon, ich fand sie nur recht umständlich, weil ich immer alle Datensätze laden muss und dann mit 3 if checken, was zutrifft.
 
Nein, du kannst IMHO COUNT() nicht mit Limit zusammen verwenden. Aber du kannst deinen Code so aufbauen, das er, wenn COUNT() größer 0 zurück liefert, trotzdem nur den ersten Datensatz abholt. Oder habe ich da jetzt was falsch verstanden?
 
Du kannst diese Abfrage aber verschachteln und als Datenmenge nutzen, auf der dann eine weiter Abfrage aufbaut, die dann LIMIT nutzt.
 
Also COUNT() liefert immer genau einen Datensatz zurück. Du kannst es machen, genau wie einfach nur crack im Post #2 schon vorgeschlagen hat, nur ohne HAVING und GROUP BY, denn es kommt ohnehin nur ein Datensatz zurück. Den liest du mit mysql_fetch_array() oder einer anderen Fetch-Funktion aus, hast den ersten gewünschten Datensatz zusammen mit der Anzahl der Datensätze, die sonst noch nach diesem Kriterien gefunden wurden.

Das ist doch das, was du erreichen willst, oder?
 
Zurück