mysql while vraag
Thomas van den Heuvel op 14/03/2015 19:39:01:
Door de manier waarom de vriendelijst-tabel in elkaar zit leent een oplossing met 1 query zich hier niet direct voor. Ook zou je je niet in allerlei moeilijke/onmogelijk bochten moeten wringen om het met 1 query op te lossen. Daarnaast heb je een ("jouw") vriendenlijst wellicht vaker nodig dus valt er best iets te zeggen om dat elke page-access opnieuw te berekenen en in een user-object op te slaan ofzo.
Tevens is er niets mis met de "verdeel en heers" strategie: deel je probleem op in deelproblemen die je afzonderlijk oplost. Ik snap de aversie voor meerdere queries niet.
Begin dus gewoon eerst eens met het opstellen van een array in PHP, waarin de gebruiker-id's van jouw vrienden zitten.
Deze bouwsteen kun je vervolgens toepassen in andere onderdelen, bijvoorbeeld queries.
Tevens is er niets mis met de "verdeel en heers" strategie: deel je probleem op in deelproblemen die je afzonderlijk oplost. Ik snap de aversie voor meerdere queries niet.
Begin dus gewoon eerst eens met het opstellen van een array in PHP, waarin de gebruiker-id's van jouw vrienden zitten.
Deze bouwsteen kun je vervolgens toepassen in andere onderdelen, bijvoorbeeld queries.
Ik zie niet in waarom je dat eerst door PHP gaat halen terwijl je het resultaat van de eerste query direct ín een andere query kan gebruiken.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT
u.gebruikersnaam,
b.datum,
b.bericht
FROM
(SELECT
CASE user_1
WHEN 1234 THEN user_2 ELSE user_1 END friend_id
FROM
vriendenlijst
WHERE
bevestigd = 1 AND (user_1 = 1234 OR user_2 = 1234)
) f
JOIN
gebruikers u
ON f.friend_id = u.user_id
JOIN
berichten b
ON f.friend_id = b.user_id
u.gebruikersnaam,
b.datum,
b.bericht
FROM
(SELECT
CASE user_1
WHEN 1234 THEN user_2 ELSE user_1 END friend_id
FROM
vriendenlijst
WHERE
bevestigd = 1 AND (user_1 = 1234 OR user_2 = 1234)
) f
JOIN
gebruikers u
ON f.friend_id = u.user_id
JOIN
berichten b
ON f.friend_id = b.user_id
die missen in een query waarvan je eerder aangaf dat die niet helemaal goed werkte.
waarom haakjes?
2*2+3 = 4+3 =7
terwijl
2*(2+3) = 2 * 5 = 10
Zo werken de regels met AND en OR ook
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
vrienden_bericht = mysqli_query($dbcreat,
"SELECT * FROM `vriendenlijst` WHERE (`naam_1`='".mysqli_real_escape_string($dbcreat,$data->login)."' or `naam_2`='".mysqli_real_escape_string($dbcreat,$data->login)."') AND `bevestigd`='1'") or die(mysqli_error($dbcreat));
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
INNER JOIN (SELECT IB.id
FROM berichten_muur AS IB
WHERE IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
vrienden_bericht = mysqli_query($dbcreat,
"SELECT * FROM `vriendenlijst` WHERE (`naam_1`='".mysqli_real_escape_string($dbcreat,$data->login)."' or `naam_2`='".mysqli_real_escape_string($dbcreat,$data->login)."') AND `bevestigd`='1'") or die(mysqli_error($dbcreat));
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
INNER JOIN (SELECT IB.id
FROM berichten_muur AS IB
WHERE IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
ik heb nu ook dit geprobeerd :
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
CROSS JOIN (SELECT IB.id
FROM berichten_muur AS IB
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
WHERE B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
CROSS JOIN (SELECT IB.id
FROM berichten_muur AS IB
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
WHERE B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
heel vreemd alles werkt maar zodra je 4 vrienden hebt gaan alle berichten van vriend 1 weg.
Gewijzigd op 15/03/2015 14:44:01 door Eeyk Vd noot
Ger van Steenderen op 15/03/2015 12:00:08:
Ik zie niet in waarom je dat eerst door PHP gaat halen terwijl je het resultaat van de eerste query direct ín een andere query kan gebruiken.
Omdat dit mogelijk niet de enige plaats is waar je je vriendenlijst gebruikt. Als je deze gegevens vaker nodig hebt dan is het omslagpunt vrij snel bereikt niet? Tenzij je elke keer zo'n super specifieke query wilt opbouwen die hetzelfde doet.
En wat als de bepaling van wie een "vriend" is verandert? Dan mag je in jouw geval een heleboel queries gaan aanpassen. Dit is dus ook een beetje risicospreiding.
Daarnaast, zoals ik al aangaf, wellicht wil je de vrienden van iemand als eigenschap / methode in een user object onderbrengen. De vriendenlijst moet dan ook "in afzondering" beschikbaar zijn, en niet als onderdeel van een andere query.
Het is fijn dat je dit specifieke probleem in 1 query kunt oplossen, maar daarbij is het niet de bedoeling dat je "the big picture" uit het oog verliest. Daarbij is 1 query meer of minder echt vele malen onbelangrijker.
Echt, laat dit "het MOET in 1 query" mantra eens los.
EDIT: En al deze mooie oplossingen ten spijt lijkt de topicstarter het nog steeds niet opgelost te hebben. Als hij gewoon mijn oplossing had gevolgd (dus gewoon aan de molen draaien, domweg 2 queries uitvoeren) dan was 'ie allang klaar geweest.
Gewijzigd op 15/03/2015 15:13:24 door Thomas van den Heuvel
Ik begrijp alleen niet waarom.
het bij vriend 1 en 2 het wel doet en dan kom je bij vriend 4 en 3 en dan ziet die geen berichten meer.
ik heb het op deze manier in me database.
het klopt dat vrid niet uniek is, dat is de code om een relatie of een vriend te blokkeren.
dat moet ik even fixen.
Gewijzigd op 15/03/2015 15:30:53 door Eeyk Vd noot
Ik zal opnieuw een poging doen om mijn strategie toe te lichten.
Stel we gaan uit van persoon X. Jij bent ingelogd als persoon X (bijvoorbeeld id 7).
Je bezoekt de berichtenmuur en je wilt je eigen berichten zien en de berichten van je vrienden.
Hiertoe bepaal je eerst wie je vrienden zijn. Hiertoe heb ik je een stuk code gegeven. Uitgaande van user X (id 7) zou dit volgens bovenstaande screenshot de volgende lijst van vrienden moeten opleveren: (6, 8, 9).
Deze informatie gebruik je vervolgens om de juiste berichten op te halen.
Die van jou (WHERE user_id = 7) of die van je vrienden (OR user_id IN (6, 8, 9)).
Wtf is precies het probleem?
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$mijnVrienden = array($ovj->id_1, $ovj->id_2);
$berichten = mysqli_query(
$dbcreat,"
'SELECT id_1, id_2 FROM vriendenlijst
WHERE (id_1 = '".$mijnvrienden[0]."' OR id_2 = '".$mijnvrienden[1]."')
AND bevestigd = '1'");
?>
$mijnVrienden = array($ovj->id_1, $ovj->id_2);
$berichten = mysqli_query(
$dbcreat,"
'SELECT id_1, id_2 FROM vriendenlijst
WHERE (id_1 = '".$mijnvrienden[0]."' OR id_2 = '".$mijnvrienden[1]."')
AND bevestigd = '1'");
?>
dit werkt niet. ik krijg het zelfde resultaat als de andere oplossingen.
ik begrijp er ook niks meer van.
Gewijzigd op 15/03/2015 15:55:50 door Eeyk Vd noot
Alleen rust kan u redden ;)
en aangepaste versies het dichtste bij kwam
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
[code]<?php
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
CROSS JOIN (SELECT IB.id
FROM berichten_muur AS IB
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
WHERE B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
Alleen het probleem is dat daar alleen alle id_1 gebruikers de berichten krijgen te zien.
[code]<?php
while($ovj = mysqli_fetch_object($vrienden_bericht)){
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
CROSS JOIN (SELECT IB.id
FROM berichten_muur AS IB
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$ovj->id_1)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
) AS IDS
ON IDS.id = B.id
WHERE B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_1)."' or B.gebruiker_id ='".mysqli_real_escape_string($dbcreat,$ovj->id_2)."'
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
}
?>
Alleen het probleem is dat daar alleen alle id_1 gebruikers de berichten krijgen te zien.
Ik kan je alleen maar aanraden om mijn vorige reactie nog eens fatsoenlijk door te lezen, en dat te combineren met mijn reactie hierboven.
Of lees al mijn reacties nog eens door, en probeer dategene te doorgronden wat je tot nu toe lijkt te ontgaan.
die oplossing geeft het zelfde resultaat als de andere.
Patric is bevriend met Jolanda en eeyk.
Eeyk is bevriend met jolanda en patric.
patric zegt : Hoi allemaal
-- eeyk ziet dit, Jolanda ziet dit.
Eeyk zegt : Hallo patric.
-- Jolanda ziet dit patric ziet dit.
Jolanda zegt : Hey allemaal.
-- Eeyk ziet dit.
Hoe kan het dat patric dit niet ziet.
Blijkbaar gaat er iets mis in het selectie-proces van de vrienden van Jolanda (of patric, zo je wil).
De vraag stellen is hem haast beantwoorden.
Je geeft zelf een situatieschets van wat er misgaat, maar je lijkt je niet te realiseren wat dit inhoudt.
"patric wordt niet beschouwd als vriend van Jolanda, waar komt dit vandaan".
Volg het spoor.
EDIT: en hierbij helpt het dus ook als je een echte relationele database hebt, waarbij referenties tussen tabellen worden afgedwongen, in plaats van dat deze als los zand aan elkaar hangen (middels usernames).
Gewijzigd op 15/03/2015 16:42:58 door Thomas van den Heuvel
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
// niet loopen over vrienden, dat doet mysql voor je...
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
INNER JOIN (SELECT IB.id
FROM berichten_muur AS IB
WHERE IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$data->id)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$data->id)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$data->id)."'
) AS IDS
ON IDS.id = B.id
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
while($loop_over_bovenstaande_query) {
echo $bericht;
}
?>
// niet loopen over vrienden, dat doet mysql voor je...
$berichten = mysqli_query($dbcreat,"
SELECT B.*
FROM berichten_muur AS B
INNER JOIN (SELECT IB.id
FROM berichten_muur AS IB
WHERE IB.gebruiker_id = '".mysqli_real_escape_string($dbcreat,$data->id)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_1 = IB.gebruiker_id
WHERE V.id_2 = '".mysqli_real_escape_string($dbcreat,$data->id)."'
UNI ON
SELECT IB.id
FROM berichten_muur AS IB
INNER JOIN vriendenlijst AS V
ON V.id_2 = IB.gebruiker_id
WHERE V.id_1 = '".mysqli_real_escape_string($dbcreat,$data->id)."'
) AS IDS
ON IDS.id = B.id
ORDER BY B.datum DESC") or die(mysqli_error($dbcreat));
while($loop_over_bovenstaande_query) {
echo $bericht;
}
?>
Dit was meer wat ik bedoelde. Sorry dat ik V.gebruikersnaam in de WHERE clauses schreef terwijl het id_1 moest zijn bij de ON id_2 en vice versa.
Quote:
Echt, laat dit "het MOET in 1 query" mantra eens los.
NOPE! Dit is iets simpels dat de database hoort te doen.
Gewijzigd op 15/03/2015 18:48:34 door Eeyk Vd noot