Gebruik van LEFT JOIN en WHERE in zelfde query
Allereerst zal ik de situatie uitleggen:
Ik heb 4 tabellen:
1) login <- Gebruikerstabel
Voorbeeld:
___________________________________________
|u_id | u_loginnaam | u_voornaam | u_achternaam |
| 1 | jaapk | Jaap | Karels |
| 2 | manager | Kees | Klaassen |
2) locaties <- Locatie van de gebruiker
Voorbeeld:
__________________________
|loc_id| loc_naam | loc_plaats |
| 1 | Beverly | Amsterdam|
3) permissies <- Permissie tabel voor verschillende permissies van de gebruiker
Voorbeeld:
___________________
|perm_id | perm_naam|
| 1 | Gebruiker |
| 2 | Manager |
4) managed <- Hierin staat welke gebruikers de manager heeft
_______________________
|m_id |m_manager| m_uid |
| 1 | 2 | 1 |
Zoals je dus ziet in bovenstaande manager met u_id 2 heeft u_id 1 in beheer!
Situatie:
Manager logt in, er wordt een sessie aangemaakt, waarin ook het u_id van die manager staat. Deze wordt in SHA1 hash variable $ses_uid gezet.
Nu wil ik met de volgende query:
Code (php)
Het gevolg is dat alle gebruikers, dus ook de gebruikers die de manager niet in zijn beheer heeft, dubbel weergegeven worden.
Ik weet zeker dat ik een beste fout maak, maar heb geen idee welke. Een groot aantal combinaties in de bovenstaande query (zoals de WHERE eerder in de query enz.) heb ik al geprobeerd, maar helaas.
Iemand enig idee, of hint?
Gewijzigd op 01/01/1970 01:00:00 door Kvdd
Volgens mij kan je niet twee keer LEFT JOIN doen, dan moet je subqueries gebruiken.
negatory, kan prima
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
SELECT
l.u_loginnaam,
l.u_voornaam,
l.u_achternaam,
p.perm_naam,
loc.loc_naam
FROM
login AS l
LEFT JOIN permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN locaties AS loc ON l.u_locatie = loc.loc_id
WHERE
managed AS m SHA1(m.m_manager) = '".$ses_uid."'
l.u_loginnaam,
l.u_voornaam,
l.u_achternaam,
p.perm_naam,
loc.loc_naam
FROM
login AS l
LEFT JOIN permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN locaties AS loc ON l.u_locatie = loc.loc_id
WHERE
managed AS m SHA1(m.m_manager) = '".$ses_uid."'
De WHERE is mij onduidelijk, wat moet managed doen? Wat heeft deze met de rest van de query te maken? Er is geen verband met de overige gegevens in deze query.
pgFrank schreef op 20.03.2008 16:08:
De WHERE is mij onduidelijk, wat moet managed doen? Wat heeft deze met de rest van de query te maken? Er is geen verband met de overige gegevens in deze query.
Als je vanaf de WHERE wegdenkt, dan doet het goed zijn werk. Maar selecteerd ALLE gebruikers.
Wat ik nu wil, dat is dat de gebruikersgegevens opgehaald worden, maar dat in dezelfde query de gebruikers die onder het beheer van die manager vallen teruggegeven worden.
Manager met u_id 2 heeft gebruiker met u_id 1 onder zijn beheer.
Met de bovenstaande query wil ik dus alleen de gebruikersgegevens ophalen van de gebruikers die onder de manager vallen.
Daar is ook die WHERE voor, maar die werkt niet.
En dat is het probleem.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
SELECT
l.u_loginnaam,
l.u_voornaam,
l.u_achternaam,
p.perm_naam,
loc.loc_naam
FROM
login AS l
LEFT JOIN permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN locaties AS loc ON l.u_locatie = loc.loc_id
WHERE
SHA1(managed.m_manager) = '".$ses_uid."'
l.u_loginnaam,
l.u_voornaam,
l.u_achternaam,
p.perm_naam,
loc.loc_naam
FROM
login AS l
LEFT JOIN permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN locaties AS loc ON l.u_locatie = loc.loc_id
WHERE
SHA1(managed.m_manager) = '".$ses_uid."'
Alleen begrijp ik sha1 niet helemaal. Dit is namelijk een codeerfunctie.
Djemo schreef op 20.03.2008 16:23:
Alleen begrijp ik sha1 niet helemaal. Dit is namelijk een codeerfunctie.
SHA1 is een hash, lees de startpost maar eens goed door, het gaat niet alleen om de query, maar om het eindresultaat wat ik graag zou willen zien :-)
Jou query geeft overigens de volgende foutmelding:
Unknown column 'managed.m_manager' in 'where clause'
Ik denk zelf dat mijn opzet in de query fout is.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?
$sUsers = mysql_query("
SELECT
m_uid
FROM
managed
WHERE
SHA1(m_manager) = "'.$ses_uid.'"
");
while ($aUsers = mysql_fetch_assoc($sUsers)){
.... (hierin komt nog een query en die staat lager in mijn post)
?>
$sUsers = mysql_query("
SELECT
m_uid
FROM
managed
WHERE
SHA1(m_manager) = "'.$ses_uid.'"
");
while ($aUsers = mysql_fetch_assoc($sUsers)){
.... (hierin komt nog een query en die staat lager in mijn post)
?>
(NB: in $ses_uid staat het u_id van de manager hé! gewoon een integer)
Nu heb ik door bovenstaande query de user id's die door manager beheerd worden.
De tweede query is dan zoiets als dit:
Code (php)
Ziet iedereen het, voilah het werkt ik heb de gebruikers die onder de manager vallen, maar bij mijn weten moet het in 1 query kunnen.
EDIT: Als je goed kijkt, zal door mijn opzet in de post hierboven, wel heel vaak een query worden uitgevoerd. ((aantalgebruikers onder beheer x 2) == aantal queries)) :-\ dat lijkt me wel heel erg veel queries!
Heeft iemand dus enig idee hoe het in 1 query kan?
Gewijzigd op 01/01/1970 01:00:00 door kvdd
mod-edit::
Bumpen
Twee of meer keer achter elkaar in een topic posten, voordat andere forumleden gereageerd hebben, heet "bumpen". Omdat het opdringerig overkomt is bumpen pas na 24 uur toegestaan. Bumpen kan een reden zijn voor de admins en mods om een topic te sluiten. Gebruik het knopje om je tekst aan te passen indien nodig.
Twee of meer keer achter elkaar in een topic posten, voordat andere forumleden gereageerd hebben, heet "bumpen". Omdat het opdringerig overkomt is bumpen pas na 24 uur toegestaan. Bumpen kan een reden zijn voor de admins en mods om een topic te sluiten. Gebruik het knopje om je tekst aan te passen indien nodig.
Dat zijn dus drie bumps in één topic. Let er even op, please.
Bedankt voor de info Jan,
Edit: is het misschien een optie om CROSS JOIN te gebruiken? Ik ben nu aan het uitpuzzelen of het op die manier wel werkt.
http://dev.mysql.com/doc/refman/5.0/en/join.html
Edit2: CROSS JOIN gaat echter ook niet werken, wat ik ook probeer. Heeft iemand een hint in de goede richting?
Gewijzigd op 01/01/1970 01:00:00 door kvdd
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
SELECT
l.u_id, l.u_loginnaam, l.u_voornaam, l.u_achternaam, l.u_pers_nr, p.perm_naam, l.u_contracttijd, l.u_parttimer, l.u_referentie, l.u_st_pauze, loc.loc_naam
FROM
login AS l
LEFT JOIN
permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN
locaties AS loc ON l.u_locatie = loc.loc_id
LEFT JOIN
managed AS m ON SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
WHERE
m.m_uid = l.u_id";
?>
SELECT
l.u_id, l.u_loginnaam, l.u_voornaam, l.u_achternaam, l.u_pers_nr, p.perm_naam, l.u_contracttijd, l.u_parttimer, l.u_referentie, l.u_st_pauze, loc.loc_naam
FROM
login AS l
LEFT JOIN
permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN
locaties AS loc ON l.u_locatie = loc.loc_id
LEFT JOIN
managed AS m ON SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
WHERE
m.m_uid = l.u_id";
?>
Het is dus opgelost, iedereen bedankt!
Mooi dat het opgelost is en goed dat je het goede antwoord hier neerzet *thumbs up*!
Dit is een inner join, waarom zet je hem dan gewoon als INNER JOIN in de query? Dat is een stuk duidelijker dan als een WHERE.
pgFrank schreef op 27.03.2008 17:56:
hmm beetje laat van me..
Maar pgFrank, jij bedoelt dat de laatste regel:
moet zijn:
Ja?
Gewijzigd op 01/01/1970 01:00:00 door kvdd
Verder gaat het hier wel om een INNER JOIN en niet een LEFT JOIN, dat zijn twee verschillende typen. De syntax is, op dat INNER na dan, precies hetzelfde.
Blanche schreef op 31.03.2008 11:06:
Nee, dat is niet de correcte syntax voor een JOIN. Kijk eens naar eerdere posts van jezelf, daar gebruik je wel de correcte syntax...
Verder gaat het hier wel om een INNER JOIN en niet een LEFT JOIN, dat zijn twee verschillende typen. De syntax is, op dat INNER na dan, precies hetzelfde.
Verder gaat het hier wel om een INNER JOIN en niet een LEFT JOIN, dat zijn twee verschillende typen. De syntax is, op dat INNER na dan, precies hetzelfde.
Ja oke, dus het zou zo moeten gaan:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
SELECT
l.u_id, l.u_loginnaam, l.u_voornaam, l.u_achternaam, l.u_pers_nr, p.perm_naam, l.u_contracttijd, l.u_parttimer, l.u_referentie, l.u_st_pauze, loc.loc_naam
FROM
login AS l
LEFT JOIN
permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN
locaties AS loc ON l.u_locatie = loc.loc_id
LEFT JOIN
managed AS m ON SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
EDIT: INNER JOIN
managed AS m ON m.m_uid = l.u_id";
?>
SELECT
l.u_id, l.u_loginnaam, l.u_voornaam, l.u_achternaam, l.u_pers_nr, p.perm_naam, l.u_contracttijd, l.u_parttimer, l.u_referentie, l.u_st_pauze, loc.loc_naam
FROM
login AS l
LEFT JOIN
permissies AS p ON l.u_permissie = p.perm_id
LEFT JOIN
locaties AS loc ON l.u_locatie = loc.loc_id
LEFT JOIN
managed AS m ON SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
EDIT: INNER JOIN
managed AS m ON m.m_uid = l.u_id";
?>
EDIT: een INNER JOIN dus, ik had eerst een AND(om de laatste LEFT JOIN langer te maken), maar dat lijkt me toch niet goed.
Gewijzigd op 01/01/1970 01:00:00 door kvdd
Dus:
Code (php)
1
2
3
4
5
2
3
4
5
LEFT JOIN
managed AS m
ON m.m_uid = l.u_id
WHERE
SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
managed AS m
ON m.m_uid = l.u_id
WHERE
SHA1(m.m_manager) = '".mysql_real_escape_string($ses_uid)."'
Gewijzigd op 01/01/1970 01:00:00 door Joren de Wit
Blanche schreef op 31.03.2008 13:21:
Je hebt het precies verkeerd om staan. De regel die jij nu als AND hebt is de voorwaarde waarop je die 2 tabellen met elkaar koppelt. De voorwaarde die jij nu in de ON clausule van die join hebt staan, hoort gewoon thuis in een WHERE clausule...
Dus:
Dus:
Ah, juist! De volgorde op mijn manier van schrijven stond dus gewoon verkeerd.
Blanche en anderen bedankt!