Utilizzo delle variabili utente per numero righe
spesso mi trovo risposte qui su SO che suggerisce l'uso di variabili utente al numero qualche cosa o altro. Forse l'esempio più chiaro sarebbe una query per selezionare ogni seconda riga da un determinato set di risultati. (Questa domanda e la domanda sono simili a this answer, ma era la risposta this che ha effettivamente attivato questa domanda qui).garanzie quando si utilizzano variabili utente alle righe numero
SELECT *
FROM (SELECT *, (@row := @row + 1) AS rownum
FROM (SELECT @row := 0) AS init, tablename
ORDER BY tablename.ordercol
) sub
WHERE rownum % 2 = 1
Questo approccio sembra funzionare normalmente.
motivi per stare attenti
D'altra parte, il MySQ docs Stato:
Come regola generale, non si dovrebbe mai assegnare un valore a una variabile utente e leggere il valore all'interno della stessa istruzione . Potresti ottenere i risultati che ti aspetti, ma questo non è garantito. L'ordine di valutazione per le espressioni che coinvolgono variabili utente non è definito e può variare in base agli elementi contenuti in una determinata istruzione; inoltre, questo ordine non è garantito essere lo stesso tra le versioni di MySQL Server.
domanda Nucleo
Quindi la mia domanda non è come realizzare un tale ordinamento utilizzando server attuali, ma invece se la soluzione suggerita utilizzando le variabili utente è garantito a lavorare in tutte le circostanze (ragionevoli) e per tutte le versioni future di MySQL.
Per "garanzie" Intendo fonti autorevoli come la documentazione di MySQL o alcune attestazioni di conformità standard di MySQL con. In mancanza di risposte autorevoli, potrebbero essere citate altre fonti come tutorial spesso usati o parti del codice sorgente MySQL. Per "funziona" Intendo il fatto che le assegnazioni verranno eseguite in sequenza, una volta per riga del risultato e nell'ordine indotto dalla riga ORDER BY
.
Esempio di una query di rottura
Per fare un esempio quanto facilmente le cose non riescono:
SELECT *
FROM (SELECT *, (@row := @row + 1) AS rownum
FROM (SELECT @row := 0) AS init, tablename
HAVING rownum > 0
ORDER BY tablename.ordercol
) sub
WHERE rownum % 2 = 1
produrrà un risultato vuoto sulla MySQL 5.5.27 attualmente installato sul SQL Fiddle. Il motivo sembra essere che la condizione HAVING
fa sì che l'espressione rownum
venga valutata due volte, quindi il risultato finale avrà solo numeri pari. Ho un'idea di cosa succede dietro le quinte e non sto affermando che la query con lo HAVING
abbia molto senso. Voglio solo dimostrare che esiste una linea sottile tra il codice che funziona e il codice che sembra molto simile ma si rompe.
@hvd, grazie per il [puntatore] (http://bugs.mysql.com/bug.php?id=35893) alla richiesta della funzione 'ROW_NUMBER'. [Dems] (http://stackoverflow.com/users/53341/dems) recentemente [mi ha detto] (http://stackoverflow.com/a/12727443) su questa funzione. Sembra abbastanza potente e ben definito per l'avvio. Peccato, sembra che ci siano pochi progressi su tale richiesta dal 2008. – MvG
Ho cancellato il mio commento quando ho visto che "ROW_NUMBER" era già menzionato nei commenti e nelle risposte alla tua domanda precedente :) – hvd
[Hai letto questo articolo già?] (http://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/) In particolare la parte 'MySQL non valuta espressioni contenenti variabili utente fino a quando non vengono inviate al client, ' –