NULL in Left Join

suntrop

Erfahrenes Mitglied
Servus. Kurz zur Situation: ein User/Datensatz wird ignoriert, wenn in einem DB-Feld für die Landeszuordnung (ud.countryId) eine „0“ steht. User soll trotzdem angezeigt werden. Wie kann ich das im Left Join notieren?

PHP:
$sql = '
	SELECT
		ud.id,
		(…)
		co.countryName AS Land,
		(…)
	FROM
		userdetails ud
	LEFT JOIN (
		users u,
		country co,
		businessbranch b
		)
		ON (
			u.id = ud.userId AND
			ud.countryId = co.id AND
			ud.businessBranchId = b.id
			)
	WHERE
		ud.visible = 1
	AND
		u.active = 1';

// Suchmöglichkeiten einschließen
// Suchfeld
if ($search != false) {
	$sql .= ' AND (';
	$sql .= 'ud.lastName LIKE "%'.mysql_real_escape_string($search).'%"';
	$sql .= ' OR ud.firstName LIKE "%'.mysql_real_escape_string($search).'%"';
	$sql .= ' OR ud.addressCity LIKE "%'.mysql_real_escape_string($search).'%"';
	$sql .= ' OR b.branch LIKE "%'.mysql_real_escape_string($search).'%"';
	if (is_numeric($search)) {
		$sql .= ' OR ('.mysql_real_escape_string($search).' >= ud.dateEntry AND '.mysql_real_escape_string($search).' <= ud.dateLeaving)';
	}
	$sql .= ')';
}
// Anfangsbuchstabe
if ($letter != false) {
	$sql .= ' AND (';
	$sql .= 'ud.lastName LIKE "'.mysql_real_escape_string($letter).'%"';
	$sql .= ')';
}
// Reihenfolge
$sql .= ' ORDER BY ud.lastName';

// Anzahl
$sql .= ' LIMIT ' . $limitStart . ', ' . $limitCount;

Die MySQL Tabelle sieht in etwa so aus:
id | name | email (…) countryId | …
Mit der countryId ermittel ich in der anderen Tabelle in welchem Land der User wohnt. Das heißt dort stehen üblicherweise Ziffern (0-240 oder so). Wenn jedoch das Land unbekannt ist, dann kann ich keine Landes-ID eintragen.

Was also tun?
 
Evtl so:

SQL:
    SELECT
        ud.id,
        (…)
        co.countryName AS Land,
        (…)
    FROM
        userdetails ud
    LEFT JOIN (
        users u,
        country co,
        businessbranch b
        )
        ON (
            u.id = ud.userId AND
            ud.countryId = co.id OR ud.countryId = 0 AND
            ud.businessBranchId = b.id
            )
    WHERE
        ud.visible = 1
    AND
        u.active = 1
 
Damit erhalte nur den Datensatz mit „0“ bei countryId und zwar sooft wie es insgesamt Datensätze gibt. Ich erhalte jetzt 31 Max Mustermänner :)

P.S.
Wie kann ich hier SQL-Code einfügen? Sehe hier nur Code, HTML und PHP Schaltflächen.
 
Hi.

NULL ist etwas anderes als '0' oder 0. Um zu überprüfen das eine Spalte NULL ist, muß man den is NULL Operator verwenden.

AND hat eine höhere Priorität als der OR Operator.

SQL Code kann man einfügen, indem man den Code in [code=sql] ... [/code] Tags schreibt.
SQL:
LEFT JOIN (
        users u,
        country co,
        businessbranch b
        )
        ON (
            u.id = ud.userId AND
            (ud.countryId = co.id OR ud.countryId is null) AND
            ud.businessBranchId = b.id
            )
Gruß
 
Zuletzt bearbeitet:
Danke für den Tipp mit dem SQL-Code.

Den exakten Unterschied zwischen NULL und 0 kenne ich zwar nicht, aber das es nicht identisch ist und anders behandelt werden muss, war mir bekannt. Dennoch danke für die Info. Hatte leider in den Themen-Titel NULL statt 0 geschrieben. In der Tabelle stand vorher eine 0.
Habe es dann auf NULL gesetzt und mit deinem Code-Vorschlag probiert. Leider auch hier wieder 31 mal der selbe Datensatz.
Auch wenn ich den SQL-Code in phpMyAdmin ausführe.

Habt ihr noch eine Idee woran es liegen könnte, oder wie ich es korrigieren kann?

Danke euch für die HIlfe!
 
Wieviel Datensätze gibt es denn?

Du weißt aber schon, das ein LEFT JOIN immer alle Datensätze aus der ersten Tabelle - in deinem Fall also aus userdetails liefert?! Es müßten alle userdetails Einträge (plus Informationen aus den verknüpften Tabellen) als Ergebnis herauskommen bei denen visible = 1 ist.

Gruß
 
Es gibt 31 Datensätze.

Der Left Join ist doch richtig hier, oder? Ich will ja alle Datensätze (Filter wird in der WHERE-Klausel gelegt, für diejenigen die visble = 0 sind) haben. Nur halt nicht 31 mal den selben :)
 
Es gibt 31 Datensätze.

Der Left Join ist doch richtig hier, oder?
Du hast nicht gesagt was genau du überhaupt machen willst.
Ich will ja alle Datensätze (Filter wird in der WHERE-Klausel gelegt, für diejenigen die visble = 0 sind) haben. Nur halt nicht 31 mal den selben :)
Innerhalb des LEFT JOIN machst du ja ein INNER JOIN der 3 Tabellen users, country und businessbranch ohne Join-Prädikate.

Was kommt denn bei
SQL:
select count(*) from users u, country co, businessbranch b
raus?

Du möchtest vermutlich sowas:
SQL:
SELECT
    ud.id,
    (…)
    co.countryName AS Land,
    (…)
FROM
    userdetails ud
    INNER JOIN users u on ud.userId = u.id
    LEFT JOIN country co on ud.countryId = co.id
    INNER JOIN businessbranch b on ud.businessBranchId = b.id
    
WHERE
    ud.visible = 1 AND u.active = 1
Gruß
 
Bislang bin ich mit Left Joins immer gut ausgekommen … sah jedenfalls immer nach dem aus, was ich wollte :)

Bei dem SELECT count(*) erhalte ich "417216" (jetzt waren 32 Datensätze in der DB gespeichert).

Dein Code-Vorschlag passt. Ich habe nur noch bei der Branche auch ein Left Join notiert, falls die Branche auch mal leer ist.
Was ich nicht so ganz verstehe, jetzt sind es doch auch Left Joins für die Länder und Branchen. Wie ich es vorher auch hatte?! Kannst du mir kurz Erklären was der Unterschied zu meiner vorherigen Schreibweise ist?

Um mal nachzuholen was ich vorhabe: Eine Liste mit Mitgliederdaten ausgeben (aus userdetails) und dazu den Benutzername (aus users) sowie Land (aus country) und Branche (aus businessbranch). Branche und Land können leer sein, bei users und userdetails dürfen die IDs natürlich niemals leer sein.

Danke dir für die klasse Hilfe!
 
Bislang bin ich mit Left Joins immer gut ausgekommen … sah jedenfalls immer nach dem aus, was ich wollte :)

Bei dem SELECT count(*) erhalte ich "417216" (jetzt waren 32 Datensätze in der DB gespeichert).

Dein Code-Vorschlag passt. Ich habe nur noch bei der Branche auch ein Left Join notiert, falls die Branche auch mal leer ist.
Was ich nicht so ganz verstehe, jetzt sind es doch auch Left Joins für die Länder und Branchen. Wie ich es vorher auch hatte?! Kannst du mir kurz Erklären was der Unterschied zu meiner vorherigen Schreibweise ist?
Wie ich schon sagte, du hattest INNER JOINS von 3 Tabellen ohne Bedingung gemacht (die dann offensichtlich 417216 Resultate lieferte). Dann hast du die userdetails Tabelle mit diesem Ergebnis mittels eines LEFT JOIN verknüpft und ein "paar" von den Resultaten durch die JOIN Kriterien und durch die WHERE Klausel wieder entfernt.

Gruß
 

Neue Beiträge

Zurück