Dá se použít ->query() s SQL CASE a zároveň zachovat ActiveRow funkcionalita?

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

Mám dotaz na DB, kde si vytvářím extra pole RANGE a pomocí CASE ho plním textem.
Vím, že to query můžu poslat natvrdo přes ->query($mujDotaz), ale právě jsem zjistil, že mi pak v šabloně nelze volat na vztahy. Příklad, u rezervace mám klíč s ID uživatele a v šabloně lze pak udělat {$rezervace->klienti[jmeno]}, ale jakmile to query vytvořím na tvrdo, tak už to nefunguje.

$od = '2016-02-01';
$do = '2016-02-29';
SELECT *, CASE
 WHEN `from` <= '$od' AND `to` >= '$do' THEN 'full'
 WHEN `from` >= '$od' AND `to` < '$do' THEN 'fits'
 WHEN `from` < '$od' AND `to` BETWEEN '$od' AND '$do' THEN 'past'
 WHEN `from` BETWEEN '$od' AND '$do' AND `to` >= '$do' THEN 'extends'
END `range`
FROM reservations
HAVING `range` IS NOT NULL

Vím, že bych to query mohl doplnit o LEFT JOIN, ale líbila se mi ta původní funkcionalita z ActiveRow..
Tudíž, dá se ten CASE napsat nějak podobně jako se píše například ->where() či ->order() ? Nebo jak jinak docílit toho abych mohl používat ActiveRow u tohodle dotazu?

David Matějka
Moderator | 6445
+
+2
-

musis vsechny hodnoty (a to nejen to $od a $do, ale i full, fits atd.) pouzit parametry

->table('reservations')
->select('*, CASE
WHEN from <= ? AND to >= ? THEN ?
WHEN from >= ? AND to < ?  THEN ?
....', $od, $do, 'full', $od, $do, 'fits', ...)
warriotox
Člen | 30
+
0
-

David Matějka napsal(a):

musis vsechny hodnoty (a to nejen to $od a $do, ale i full, fits atd.) pouzit parametry

Mockrát díky za rychlou odpověd. Doplnil jsem to, ale háže to chybu:

Nette\Database\DriverException #42000

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM `reservations`' at line 5.

Doplněný kód:

$db=$this->database->table('reservations')
            ->select('*, CASE
                WHEN from <= ? AND to >= ? THEN ?
                WHEN from >= ? AND to < ?  THEN ?
                WHEN from < ? AND to BETWEEN ? AND ? THEN ?
                WHEN from BETWEEN ? AND ? AND to >= ? THEN ?'
                ,$od, $do, 'full'
                ,$od, $do, 'fits'
                ,$od, $od, $do, 'past'
                ,$od, $do, $do, 'extends');

Posalný query vypadá takhle:

SELECT *, CASE
 WHEN `from` <= '2016-02-16' AND `to` >= '2016-02-23' THEN 'full'
 WHEN `from` >= '2016-02-16' AND `to` < '2016-02-23' THEN 'fits'
 WHEN `from` < '2016-02-16' AND `to` BETWEEN '2016-02-16' AND '2016-02-23' THEN 'past'
 WHEN `from` BETWEEN '2016-02-16' AND '2016-02-23' AND `to` >= '2016-02-23' THEN 'extends'
FROM `reservations`

Není nutné tam nějak dopsat ještě to END RANGE a HAVING RANGE IS NOT NULL?

David Matějka
Moderator | 6445
+
+2
-

ano, jen se mi to nechtelo psat cele. to end napis do selectu a having pomoci metody https://api.nette.org/…lection.html#…

warriotox
Člen | 30
+
0
-

David Matějka napsal(a):

ano, jen se mi to nechtelo psat cele. to end napis do selectu a having pomoci metody https://api.nette.org/…lection.html#…

Aha, já vždy čekám nějáke složité řešení, tak mě to ani nenapadlo skusit. Mockrát děkuji.
Pro info, kompletní query:

$db=$this->database->table('reservations')
            ->select('*, CASE
                WHEN from <= ? AND to >= ? THEN ?
                WHEN from >= ? AND to < ?  THEN ?
                WHEN from < ? AND to BETWEEN ? AND ? THEN ?
                WHEN from BETWEEN ? AND ? AND to >= ? THEN ? END `range`'
                ,$od, $do, 'full'
                ,$od, $do, 'fits'
                ,$od, $od, $do, 'past'
                ,$od, $do, $do, 'extends')->having('`range` IS NOT NULL');