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
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
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
@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
@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! :)