Meerdere queries ombouwen naar 1
Ik ben bezig met een klein scriptje om een overzicht mee te kunnen uitdraaien. Nu heb ik het overzicht al (omdat het snel moest worden geleverd) maar volgens mij is het niet 'efficient'. Vandaar de vraag of iemand een betere manier weet om dit op te lossen:
Ik heb op dit moment 3 tabellen:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
user
----
id
name
diploma
----
id
number
date
user_id
type_id
diplomaType
----
id
name
?>
user
----
id
name
diploma
----
id
number
date
user_id
type_id
diplomaType
----
id
name
?>
Wat ik wil is van elke user alle diploma's ophalen na 2015. Op dit moment heb ik dat opgelost door eerst alle gebruikers op te halen met een query en vervolgens per gebruiker alle diploma's op te halen.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
$users = 'select id from user'; //het hele prepared gebeuren heb ik hier weggehaald om het kort te houden.
foreach($users as $u)
{
$diplomas = select u.name, d.number, dt.name from user u
JOIN diploma d on u.id = d.user_id
JOIN diplomaType dt ON d.type_id = dt.id
WHERE u.id = $u AND DATE(YEAR) > 2015; //deze dingen merge ik naar een array als resultaat
}
?>
$users = 'select id from user'; //het hele prepared gebeuren heb ik hier weggehaald om het kort te houden.
foreach($users as $u)
{
$diplomas = select u.name, d.number, dt.name from user u
JOIN diploma d on u.id = d.user_id
JOIN diplomaType dt ON d.type_id = dt.id
WHERE u.id = $u AND DATE(YEAR) > 2015; //deze dingen merge ik naar een array als resultaat
}
?>
Heb niet het hele script gepost anders wordt het zo lang. Nu zijn er 500 users wat betekent dat ik 500x de join query moet uitvoeren. Is het mogelijk om een overzicht uit de database te halen zonder te loopen door alle users en 500x een query uit te voeren? Want volgens mij is dit aardig 'inefficient'?
--edit code tags toegevoegd--
Gewijzigd op 14/06/2017 10:09:18 door Ama saril
En dat is niet nodig, want je selecteert nu per gebruiker opnieuw. Kijk maar eens naar de 2e query. Als je hier de user conditie uit weglaat ben je al klaar.
Ben van Velzen op 14/06/2017 10:41:09:
En dat is niet nodig, want je selecteert nu per gebruiker opnieuw. Kijk maar eens naar de 2e query. Als je hier de user conditie uit weglaat ben je al klaar.
Niet helemaal ingeval een gebruiker meerdere diploma's kan hebben? In dat geval zou je een LEFT JOIN van users op diploma's moeten doen.
EDIT: of de resulterende query efficiënt is hangt ook af van het type database(-engine) en of (en hoe) de relaties zijn gedefinieerd. Indien je de MyISAM engine gebruikt doe je er verstandig aan om indexen aan te maken op user_id en type_id. Nadeel van deze engine is dat tabellen nog steeds enigszins als los zand aan elkaar hangen. Indien je de InnoDB engine gebruikt zouden user_id en type_id al foreign key constraints moeten zijn naar hun bijbehorende tabellen. Voordeel van deze methode is dat dit soort relaties (op databaseniveau) de integriteit van de data in deze tabellen (beter) waarborgen.
Gewijzigd op 14/06/2017 11:01:47 door Thomas van den Heuvel
Uhm.. Waarom? Een LEFT JOIN is alleen van toepassing wanneer je verwacht dat er gevallen zijn waar je 0 resultaten kan krijgen en je alsnog de user zou willen zien.
Los hiervan, om dit soort beslissingen te nemen ((INNER) JOIN vs LEFT JOIN etc.) zul je meer moeten weten over het gedrag van de data in kwestie.
Zie ook mijn toevoeging over efficiëntie in mijn vorige reactie.
Niet echt. Het houdt in dat de user gedupliceerd wordt per diploma. Een LEFT JOIN is 0 of meer, INNER is 1 of meer.
Bedankt voor de snelle reacties. Ik zal alle suggesties even uittesten zodra ik weer thuis ben vanavond. Ik zal de resultaten hier posten.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
SELECT u.name, d.number, dt.name
FROM user u
JOIN diploma d on u.id = d.user_id
JOIN diplomaType dt ON d.type_id = dt.id
WHERE AND YEAR(d.date) > 2015
ORDER BY u.name
FROM user u
JOIN diploma d on u.id = d.user_id
JOIN diplomaType dt ON d.type_id = dt.id
WHERE AND YEAR(d.date) > 2015
ORDER BY u.name
Je filter op jaartal klopte niet.
En ik zou ze sorteren op naam: dan krijg je alle records per naam achterelkaar.
Als iemand dan 2 of meer diploma's heeft, komen die achter elkaar aan bod. Dan kun je eventueel zorgen dat bij het weergeven je de naam niet steeds herhaalt.