Pomoc! Seřadit hráče podle součtu tří hodnot z cizí tabulky přičtených k hodnotě v další tabulce

matronator
Člen | 38
+
0
-

Zdravím, pro jistotu postuji i zde v českém foru, protože se bojím že na tom anglickém to moc lidí neuvidí. Nevím zda se to sem hodí, jelikož to není přímo čistě Nette problém, ale nevím si rady a opravdu potřebuji pomoct jelikož SQL není moje silná stránka, co se komplexních dotazů týče.

Mám tři tabulky, které jsou relevantní k tomuto problému (zkrácené pouze na podstatné sloupce). První je tabulka user:

id username player_stats_id
1 matronator 1
2 terminator 2
3 dominator 3

Druhá je player_stats:

id power
1 230
2 78
3 121

A třetí je player_gear_stats, která ale nemusí pro každého hráče existovat:

id user_id strength stamina speed
1 1 10 0 3
2 3 6 1 1

A z tohoto bych potřeboval vytáhnout seznam hráčů seřazený podle power z player_stats tabulky, sečtenou s strength, stamina a speed z tabulky player_gear_stats.

Když jsem ten žebříček dělal poprvé, tak ve hře nebyli žádné itemy, tudíž žádná player_gear_stats tabulka. Takže toho bylo docela jednoduše docíleno tímto kodem:

public function findUsersForLeaderboard()
{
    return $this->database->table('user')->order('player_stats.power DESC');
}

Ale teď potřebuji řadit podle jejich síly spojené se sílou (síla = strength + stamina + speed) jejich vybavení, která je uložená v té player_gear_stats tabulce.

Může mi někdo prosím poradit jak na to? Já se v tomhle ztrácím. Ideálně řešení které používá Nette\Database\Explorer, ale budu vděčný i za čisté SQL.

Předem moc díky!

matronator
Člen | 38
+
0
-

Tak už jsem přišel na to jak to udělat pomocí raw SQL s použitím proměnných. Můžu nějak použít SQL variables v Database Exploreru?

Ten dotaz vypadá takto:

SELECT *,
  @gearStats := IFNULL(`player_gear_stats`.`strength` + `player_gear_stats`.`stamina` + `player_gear_stats`.`speed`, 0)  AS `gear_power`,
  @gearStats + `player_stats`.`power` AS `total_power`
FROM `user`
LEFT JOIN `player_stats` ON `user`.`player_stats_id` = `player_stats`.`id`
LEFT JOIN `player_gear_stats` ON `user`.`id` = `player_gear_stats`.`user_id`
ORDER BY `player_stats`.`power` + IFNULL(`gear_power`, 0) DESC
LIMIT 10;
uestla
Backer | 799
+
+1
-

@matronator Mělo by to jít přes backjoin (https://doc.nette.org/…ase/explorer#…):

$leaderboard = $explorer->table('user')
	->order('
		(IFNULL(player_stats.power, 0)
			+ IFNULL(:player_gear_stats.strength, 0)
			+ IFNULL(:player_gear_stats.stamina, 0)
			+ IFNULL(:player_gear_stats.speed, 0)
		)
		DESC
	')
;
matronator
Člen | 38
+
0
-

@uestla Super, moc děkuju, funguje! Dokumentaci jsem sice četl, ale trochu jsem se v těch vazbách ztrácel, takže tohle by mě v životě nenapadlo. Díky! :)