Week 7

Deze week was niet zo bijzonder in de zin dat er niet veel noemenswaardig gebeurd is. Het merendeel van deze week bestond uit het oplossen van bugs, polishing en meer testen.

Meer queries

Vorige week evalueerde ik verschillende mogelijkheden bij het ophalen van reizen en de bijhorende reisaanbiedingen. Ik vermeldde dat de performantie van de laatste oplossing die ik gebruikte waarschijnlijk het beste was. Om de query er even terug bij te nemen:

SELECT * FROM productoffers po INNER JOIN products p WHERE meets_criterium_1 AND meets_criterium_2 AND … GROUP BY po.product_id ORDER BY column LIMIT 10

Het probleem hiermee was dat ik na het ophalen van alle reizen (hier producten genoemd) over de resultaten moest itereren om de bijhorende aanbiedingen op te halen. Na wat meer opzoekwerk na mijn vorige blogpost ben ik toch op een betere oplossing uitgekomen. De oplossing is beter in de zin dat hij performanter is, maar door sommigen misschien als “hacky” ervaard zou kunnen worden.

SELECT po.*, ‘#’, p.*, COUNT(*) AS count FROM productoffers po INNER JOIN products p WHERE meets_criterium_1 AND meets_criterium_2 AND … GROUP BY p.id ORDER BY column LIMIT 10

De parameter count laat ons uiteraard weten hoeveel aanbiedingen er per reis zijn. Wat is hier nu precies zo speciaal aan? Op deze manier weet je bij het itereren hoeveel aanbiedingen er bij de query aan de filter voldeden (je kan niet meer dan één aanbieding ophalen per reis, maar je kan wel het totale aantal opvragen). Dit laat ons toe de volgende werkwijze te hanteren:

$results = execute_query_and_retrieve_rows($query);

foreach($results as &$result)
{
	if($result['count'] == 1) {
		// Splits $result in twee: alle elementen voor en na het hekje '#'.
		$result['offers] = array(extract_elements_before_symbol_as_array('#'));
		// Eventueel kunnen de 'verkeerde' elementen uit result verwijderd worden,
		// maar als deze niet gebruikt worden is dit niet nodig.
	} else {
		// Doe zoals voorheen en haal alle bijhorende aanbiedingen op:
		$result['offers'] = execute_query_and_retrieve_rows($otherQuery);
	}
}

Merk ook op dat de volgorde van po.*, ‘#’, p.* significant is omdat er twee ID’s als key terecht zullen komen in het eindresultaat. Aangezien zo’n result een associatieve array is, zal enkel de laatste ID behouden worden (diegene van het product). (Als je deze methode toepast, pas dan ook op dat de twee tabellen geen andere velden hebben met dezelfde naam (zoals ID), hiervoor geldt hetzelfde.) Aangezien er meer resultaten zijn die slechts één aanbieding hebben dan resultaten die meerdere aanbiedingen hebben, kan dit een redelijke sprong in performantie betekenen; hier moet namelijk geen extra query meer voor uitgevoerd worden.

In dit voorbeeld had ik geen nood aan de ID van de aanbieding die “wegvalt”. Als dit wel het geval mocht zijn, kan dit eventueel opgevangen worden door de namen van de velden uit de eerste tabel (hier productoffers) uit te schrijven i.p.v. de wildcard po.* te gebruiken. De ID krijgt dan bv. de alias po_id en kan eventueel in de if-statement bovenaan veranderd worden naar id. Hetzelfde geldt voor products. Het nadeel van deze methode is dan weer dat als er een nieuw veld wordt toegevoegd aan de tabel en dit ook mee opgehaald moet worden, de query moet worden aangepast. Jammer genoeg kan je niet altijd alles hebben…

Reactie plaatsen

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

*