MySQL: GROUP_CONCAT() méretének növelése a sessionben

Sokan elkövetik azt a hibát, hogy a MySQL lekéréseket PHP ciklusba teszik, mert másképpen szerintük nem megoldható, hogy több soros eredményt tegyünk bele 1 SQL cellába a lekérdezés eredményénél. Ez a rossz módszer természetesen nagyon erőforrás pazarló és a weboldalak sebesség problémáinak nagy részét is ez okozza.

Az egyik jó megoldás ennek elkerülésére, ha a GROUP_CONCAT() paranccsal egyesítjük a subquery sorait. Viszont alapértelmezetten ebbe csak viszonyag rövid eredmény fér, így nagy eséllyel le lesz vágva a válasz vége. A méret néveléshez adjuk ki az SQL kérés előtt a következő parancsot:

SET SESSION group_concat_max_len = 100000;

Például így lehet nem JSON képes ( 🙁 ) MariaDB-ből JSON tömböt csinálni – kicsit csúnyán – egy subqueryben:

SELECT 
	DISTINCT(rcc.company_parent_id) AS ID,
	c.compname AS Name,
	CONCAT(
		'[', 
		GROUP_CONCAT(
			(
				SELECT CONCAT('{"ID":', c2.oid, ',"Name":"', c2.compname, '","LangCode":', c2.langcode, '}')
				FROM companies c2 
				WHERE c2.oid = rcc.company_child_id  AND c2.is_disabled = 0
			)
		),
		']'
	) AS CompanyChildren
FROM rel_company_company rcc
LEFT OUTER JOIN companies c
	ON c.oid = rcc.company_parent_id
WHERE FIND_IN_SET( 'device_media_share', ret_type ) AND c.is_disabled = 0

Például részlet PDO-s változatból:

$DB->exec('SET SESSION group_concat_max_len = 100000;');

$q = <<<SQL
SELECT 
	DISTINCT(rcc.company_parent_id) AS ID,
	c.compname AS Name,
	CONCAT(
		'[', 
		GROUP_CONCAT(
			(
				SELECT CONCAT('{"ID":', c2.oid, ',"Name":"', c2.compname, '","LangCode":', c2.langcode, '}')
				FROM companies c2 
				WHERE c2.oid = rcc.company_child_id  AND c2.is_disabled = 0
			)
		),
		']'
	) AS CompanyChildren
FROM rel_company_company rcc
LEFT OUTER JOIN companies c
	ON c.oid = rcc.company_parent_id
WHERE FIND_IN_SET( 'device_media_share', ret_type ) AND c.is_disabled = 0
SQL;

$st = $DB->prepare(trim($q));
$st->execute([]);

$ret->result = $st->fetchAll(PDO::FETCH_OBJ);

foreach($ret->result as $r) {
 $r->CompanyChildren = json_decode($r->CompanyChildren);
}


echo json_encode($ret);
...