Složitější where podmínka
- jtousek
- Člen | 951
Potřeboval bych z databáze vybrat všechny uživatele, kteří mají jinou roli než „client“ (i takové, kteří mají roli „client“ a ještě nějakou jinou.
V SQL je dotaz relativně jednoduchý:
SELECT `id`, `name`
FROM `user`
WHERE EXISTS(
SELECT role.id
FROM user_role
JOIN role
ON user_role.role_id = role.id
WHERE user_role.user_id = user.id
AND role.name != "client"
)
Problém je, že bych tohle potřeboval jako where podmínku do Selection. Zkoušel jsem toto (i variantu jen string bez new SqlLiteral):
$selection->where(new \Nette\Database\SqlLiteral('EXISTS( SELECT role.id FROM user_role JOIN role ON user_role.role_id = role.id WHERE user_role.user_id = user.id AND role.name != "client" )'))
Výsledek: „No reference found for $user->user_role.“. NDB se snaží z dané podmínky vytvořit joiny, což v daném případě není žádoucí. Lze to nějak obejít?
EDIT: Odpovím si sám: ano lze. :-)
$selection->where('1', new \Nette\Database\SqlLiteral('EXISTS( SELECT role.id FROM user_role JOIN role ON user_role.role_id = role.id WHERE user_role.user_id = user.id AND role.name != "client" )'));
Editoval jtousek (30. 9. 2012 10:29)
- petr.pavel
- Člen | 535
Obvykle se snažím dotaz předělat tak, aby šel do NDB/NotORM zapsat hezky. Co takhle (psáno z hlavy):
$db->table('user')
->where('NOT user_role:role.name', 'client')
->where('NOT role.id', null)
->group('user.id');
Syntaxi mám z NotORM, už jsem dlouho nedělal v NDB, tak nevím, jak je to tam teď se dvojtečkama v „user_role:role.name“.
NotORM připojuje přes LEFT JOIN, takže se vlastně snažím převést tvoje EXISTS na LEFT JOIN a pak odfiltrovat uživatele bez připojených rolí.
- jtousek
- Člen | 951
Díky, to mne sice napadlo taky ale NDB používá INNER JOIN a momentálně to nejde změnit.
- Caine
- Člen | 216
Pokud potrebujes jen ten dotaz v uvodu, aniz bys ho nejak pres selection upravoval, tak pouzij ten dotaz primo $database->query(‚SELECT …‘) viz https://doc.nette.org/cs/database#…
Jinak to zatim obejit nejde (bez zasahovani do zdrojaku NDB)..