Seřazení záznamů na základě podmínky

ForestCZE
Člen | 209
+
0
-

Ahoj, snažím se seřadit záznamy dle podmínky následovně:

return $this->database->getTournaments()->where('removed', false)->order('active DESC, (CASE WHEN active = ? THEN start_date, start_time ELSE start_date DESC, start_time DESC END)', true);

Vyhodí to error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' `start_time ELSE start_date DESC, start_time DESC END) LIMIT 20' at line 1`

Je možné to nějak takto podobně použít?

pux
Člen | 14
+
+1
-

CASE neumožňuje návrat více výrazů, viz. citace ze StackOveflow:

CASE is an expression – it returns a single scalar value (per row). It can't return a complex part of the parse tree of something else, like an ORDER BY clause of a SELECT statement.

Napadá mě zkusit ORDER BY část rozepsat:

ORDER BY active DESC,
CASE WHEN active = true THEN start_date END,
CASE WHEN active = true THEN start_time END,
CASE WHEN active = false THEN start_date DESC END,
CASE WHEN active = false THEN start_time DESC END

Výsledek by tedy byl:

return $this->database->getTournaments()->where('removed', false)->order('ORDER BY active DESC, CASE WHEN active = ? THEN start_date END, CASE WHEN active = ? THEN start_time END, CASE WHEN active = ? THEN start_date DESC END, CASE WHEN active = ? THEN start_time DESC END', true, true, false, false);
ForestCZE
Člen | 209
+
0
-

pux napsal(a):

CASE neumožňuje návrat více výrazů, viz. citace ze StackOveflow:

CASE is an expression – it returns a single scalar value (per row). It can't return a complex part of the parse tree of something else, like an ORDER BY clause of a SELECT statement.

Napadá mě zkusit ORDER BY část rozepsat:

ORDER BY active DESC,
CASE WHEN active = true THEN start_date END,
CASE WHEN active = true THEN start_time END,
CASE WHEN active = false THEN start_date DESC END,
CASE WHEN active = false THEN start_time DESC END

Výsledek by tedy byl:

return $this->database->getTournaments()->where('removed', false)->order('ORDER BY active DESC, CASE WHEN active = ? THEN start_date END, CASE WHEN active = ? THEN start_time END, CASE WHEN active = ? THEN start_date DESC END, CASE WHEN active = ? THEN start_time DESC END', true, true, false, false);

Wow, moc děkuju. Vypadá to logicky, i když je to delší. Spíše jsem se začínal pomalu smiřovat s tím, že to nepůjde.

Musel jsem tedy odstranit ORDER BY, které tam bylo navíc kvůli té funkci order(), nicméně je prý stále chyba v syntaxi:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DESC END, CASE WHEN `active = 0 THEN start_time DESC END LIMIT 20' at line 1`

Tracy vyhodí dotaz v podobě:

SELECT `id`, `logo`, `name`, `ongoing`, `start_date`, `start_time`, `mode_id`, `current_teams`,
`max_teams`, `active`
FROM `tournaments`
WHERE (`removed` = ?)
ORDER BY `active` DESC, CASE WHEN `active` = ? THEN `start_date` END, CASE WHEN `active` = ? THEN
`start_time` END, CASE WHEN `active` = ? THEN `start_date` DESC END, CASE WHEN `active` = ? THEN
`start_time` DESC END
LIMIT 20
return $this->database->getTournaments()->where('removed', false)->order('active DESC, CASE WHEN active = ? THEN start_date END, CASE WHEN active = ? THEN start_time END, CASE WHEN active = ? THEN start_date DESC END, CASE WHEN active = ? THEN start_time DESC END', true, true, false, false);

Vypadá to, že ta funkce order() nechce vzít argumenty. Proč?
EDIT: Koukám, že ani where() nevezme argument, přitom normálně ano…

Editoval ForestCZE (6. 4. 2021 6:21)

David Matějka
Moderator | 6445
+
+1
-

ani desc nemůžeš z case „vrátit“, potřebuješ nejdříve neseřadit ty neaktivní a až v dalším orderu je seřadit sestupně:

ORDER BY
	active DESC,
	CASE WHEN active = 0 THEN NULL ELSE start_date END,
	CASE WHEN active = 0 THEN NULL ELSE start_time END,
	start_date DESC,
	start_time DESC
ForestCZE
Člen | 209
+
0
-

Snad nebude vadit, když znovu „otevřu“ vlákno. Týká se to stejného problému a nechci kvůli tomu zakládat nové vlákno.

Mám tabulku employees a v ní sloupce:
job, job_grade
job1, job_grade1
job2, job_grade2

Ten zaměstnanec dostane hodnotu jobu například ambulance, ale může tu hodnotu dostat do jednoho ze tří sloupců (job, job1, job2), podle jeho volného slotu. Následně dostane číslo pozice od 0 do 7 do příslušného sloupce podle jobu. Takže pokud je to např. job1, pak dostane číslo pozice do job_grade1 a nikam jinam.

Rád bych seřadil job_grade, job_grade1 a job_grade2 od nejvyšší pozice po nejnižší, tedy sestupně. Problém ale je, že je to závisle na tom jobu. Tudíž když udělám:

order('job_grade DESC, job_grade1 DESC a job_grade2 DESC')

tak zaměstnanec s job_grade: 6 bude výše než zaměstnanec s job_grade1: 7, neboť se job_grade řadí dříve. Lze to nějak udělat, aby se to řadilo nezávisle?

Zkusil jsem:

... ->order('CASE WHEN job = ? THEN job_grade DESC END, CASE WHEN job1 = ? THEN job_grade1 DESC END, CASE WHEN job2 = ? THEN job_grade2 DESC END', self::JOB, self::JOB, self::JOB);

což nelze, jelikož, jak už tady bylo zmíněno, DESC nelze z CASE „vrátit“. Jak na to tedy? Díky moc předem.

Editoval ForestCZE (17. 6. 2021 4:07)

David Matějka
Moderator | 6445
+
0
-

ten směr řazení (DESC) dej až za CASE (resp za END)

ForestCZE
Člen | 209
+
0
-

David Matějka napsal(a):

ten směr řazení (DESC) dej až za CASE (resp za END)

@DavidMatějka to už jsem také zkoušel. QUERY v laděnce:

ORDER BY CASE WHEN `job` = 'ambulance' THEN `job_grade` END DESC, CASE WHEN `job1` = 'ambulance' THEN `job_grade1` END
DESC, CASE WHEN `job2` = 'ambulance' THEN `job_grade2` END DESC

Šablona – řadí se to špatně – boss by měl být nahoře