Složitější where podmínka

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
jtousek
Člen | 951
+
0
-

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
+
0
-

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
+
0
-

Díky, to mne sice napadlo taky ale NDB používá INNER JOIN a momentálně to nejde změnit.

petr.pavel
Člen | 535
+
0
-

Šit.

Caine
Člen | 216
+
0
-

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)..

jtousek
Člen | 951
+
0
-

@Caine: Promiň pozdní reakci. :-) Dále upravovat přes selection sice nyní nepotřebuji, ale později to možná potřeba bude. V každém případě to předávám komponentě, která počítá s tím, že dostane Selection. Ale jak už jsem psal v „EDIT“, dokázal jsem to obejít. :-)

Caine
Člen | 216
+
0
-

Vsiml jsem, ja jsem potreboval neco podobnyho, ale u order by, a tam se to takhle obejit nedalo:)