Newsgroup: it.comp.www.php
Titolo: Mysql, prima tutti i record con valore X, poi gli altri

Vorrei fare una query sola che mi permettesse di specificare che voglio 
che nel recordset siano restituiti prima tutti i record con campo Z = X 
e poi tutti gli altri.
Non posso usare ORDER BY perchï¿œ il valore X non ï¿œ nï¿œ il primo nï¿œ 
l'ultimo in ordine alfabetico.
Esiste il modo?
Vi ringrazio.

Esiste il modo?
Brutto:
	ORDER BY CASE WHEN Z=X THEN 'AAA' ELSE Z END;
mysql> CREATE TABLE test ( z varchar(20) );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO test VALUES ('Aleksei'), ('Boris'), ('Cyril'),
('Dmitri');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> SELECT z FROM test ORDER BY CASE WHEN z = 'Dmitri' THEN 'AAA' ELSE
z END;
+---------+
| z       |
+---------+
| Dmitri  | <---------
| Aleksei |
| Boris   |
| Cyril   |
+---------+
4 rows in set (0.00 sec)
Certo, ti tocca trovare una stringa certamente minore di tutte le altre.
Leonardo
-- 
Linten addie toorin addie,
Linten addie toorin ee,
Linten lowrin lowrin lowrin,
The barnyards of Delgaty

 Certo, ti tocca trovare una stringa certamente minore di tutte le altre.
i numeri vengono prima, meglio '0000'

 	ORDER BY CASE WHEN Z=X THEN 'AAA' ELSE Z END;
Serni sei sempre un grande.
Per� ho un problema in pi� che il case non mi risolve.
Ipotiziamo la tabella
campi:
	Z	Y
record:
	V	6
	V	4
	V	7
	F	2
	F	5
	P	1
	P	3
Io nel recordset vorrei prima tutti i record con Z=V ordinati per Y, poi 
tutti i record con Z<>V ordinati sempre per Y.
Mentre la tua soluzione mi permette di ordinare solo per Z e solo in 
seconda battuta per altri campi.
Quindi a me servirebbe:
	Z	Y
	V	4
	V	6
	V	7
	P	1
	F	2
	P	3
	F	5
Mentre con quel case ottengo:
	Z	Y
	V	4
	V	6
	V	7
	F	2
	F	5
	P	1
	P	3
Ci sono soluzioni?
Mi tocca fare due query?
C'� modo almeno di concatenare due query in maniera che da php io 
ottenga un recordset unico?
Grazie mille.

Sto tentando un
(SELECT ... ORDER BY ...) UNION (SELECT ... ORDER BY ...)
ma Phpmyadmin esplode! Rimane l� a tentar di caricare la pagina ma senza 
riuscire.
La query comunque non risulta stia girando sul database, quindi la colpa 
� di Phpmyadmin.
Va be' comunque mi sto rassegnando a fare una union di due query.
Confermi che non ci siano altre uscite migliori?

Ci sono soluzioni?
Inoltre, se lavori con PHP, puoi usare uasort(), e farti una tua funzione
di ordinamento che ordini tuple. Pero' devi caricarti tutta la tabella in
memoria come array di array. Scalabilita' addio.
function ordinamengo($tupla1, $tupla2)
{
	if (('X' == $tupla1['z'])
		^^ /* Questo vorrebbe essere uno XOR */
	    ('X' == $tupla2['z'])
	{
		if ($tupla1['y'] < $tupla2['y'])
			return -1;
		else if ($tupla1['y'] > $tupla2['y'])
			return 1;
		return 0;
	}
	return ('X' == $tupla1['z']) ? -1 : 1;


 memoria come array di array. Scalabilita' addio.
Non posso perch� i risultati sono paginati con LIMIT sulla query.
Anzi, si potr� applicare il LIMIT a due query unite con UNION? Speriamo.

Anzi, si potr� applicare il LIMIT a due query unite con UNION? Speriamo.
A due query generiche si'. E' se usi ORDER BY che non so come ti vada. Non
puoi fare una cosa come
	SELECT * FROM test WHERE z='pippo' ORDER BY y
	UNION
	SELECT * FROM test WHERE z!='pippo' ORDER BY y
	[LIMIT ...];


 	[LIMIT ...];
Andando di parentesi?
(SELECT ... ORDER BY ...) UNION (SELECT ... ORDER BY ...) LIMIT ...

>> ORDER BY CASE WHEN Z=X THEN Y - K ELSE Y END;
Che ne dici invece di
SELECT *, case when Z=X then 1 else 0 end as orderbyfield
FROM nometabella
ORDER BY orderbyfield DESC;
segnalato su it.lavoro.professioni.webmaster ?
Sembra perfetta!

tenerne conto).
Per poche righe non penso faccia differenza, ma per molte righe mi aspetto
che il <boolean> vada pressappoco al doppio-triplo della velocita'.
CREATE TABLE test ( z integer, y integer );
INSERT INTO test VALUES ( 1, 1 ), ( 1, 2 ), ( 1, 3 ), ( 1, 4 );
INSERT INTO test VALUES ( 2, 1 ), ( 2, 2 ), ( 2, 3 ), ( 2, 4 );
INSERT INTO test SELECT z, y + 4 WHERE z = 2;
INSERT INTO test SELECT z, y + 4 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 8 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 16 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 32 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 64 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 128 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 256 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 512 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 1024 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 2048 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 4096 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 8192 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 16384 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 32768 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 131072 FROM test WHERE z = 2;
INSERT INTO test SELECT z, y + 262144 FROM test WHERE z = 2;
CREATE INDEX test_ndx ON test ( z, y );
mysql> ( SELECT * FROM test WHERE z = 1 ORDER BY y ) UNION ( SELECT * FROM
test WHERE z != 1 ORDER BY y ) LIMIT 100000, 3;
+------+--------+
| z    | y      |
+------+--------+
|    2 | 165533 |
|    2 | 165534 |
|    2 | 165535 |
+------+--------+
3 rows in set (0.48 sec)
mysql> SELECT * FROM test ORDER BY z != 1, y LIMIT 100000, 3;
+------+--------+
| z    | y      |
+------+--------+
|    2 | 165533 |
|    2 | 165534 |
|    2 | 165535 |
+------+--------+
3 rows in set (0.12 sec)
...quattro volte. Dipende comunque dalla cardinalit� degli indici e da un
vallo di altre cose.
E, ovviamente, il trucco funziona bene SOLO se hai UNA categoria che vuoi
mettere in cima. Gia' se ne hai due diventa complesso, e ti conviene fare
una combinazione binaria dei vari casi (4*(z!=1)+2*(z!=2)+1*(z!=3)...), o
la composizione di indici ti uccide.
La UNION, beh, ti costa comunque una bomba: che tu faccia LIMIT 1, 2 o tu
faccia LIMIT 100000, 2 ti costa sempre il massimo... e questo e' un altro
motivo per evitare.
Per query piu' complesse, l'unica e' andare di CASE. Oppure, che cosi' si
rimane in topic, uasort().


 Sembra perfetta!
Che ne pensi?




Be', equivale all'ordinamento booleano.
	CASE WHEN Z=X THEN 1 ELSE 0 END
e' la stessa cosa che dire
	Z=X
...vale 1 se Z=X, 0 altrimenti.
E' molto probabile che in MySQL si riduca allo stesso pseudocodice quando
va a fare l'ottimizzazione della query.
Ha il vantaggio di essere piu' flessibile:
	CASE WHEN Z=X1 THEN 0 WHEN Z=X2 THEN 1 ... ELSE N END;
e in questo caso forse conviene rispetto a
	((Z=X1)+2*(Z=X2)+4*(Z=X3)+...2^N)
perche' penso che l'optimizer i CASE li riconosca e le espressioni magari
no.
La grossa differenza di prestazioni pero' e' fra UNION e non UNION, IMHO.


 La grossa differenza di prestazioni pero' e' fra UNION e non UNION, IMHO.
Grazie di tutto.

> ORDER BY CASE WHEN Z=X THEN 'AAA' ELSE Z END;
aggiungi ,Y
ORDER BY CASE WHEN Z=X THEN 'AAA' ELSE Z END, Y
[cut]
ciao
Max