2013-05-23 7 views
16

Esiste la possibilità di fare qualcosa del genere?MySQL - Definisci una variabile all'interno di select e usala all'interno dello stesso select

SELECT 
    @z:=SUM(item), 
    2*@z 
FROM 
    TableA; 

Ottengo sempre NULL per la seconda colonna. La cosa strana è che, mentre si fa qualcosa come

SELECT 
    @z:=someProcedure(item), 
    2*@z 
FROM 
    TableA; 

tutto funziona come previsto. Perché?

+1

Mi aspetto molto '@z: = someProcedure (item), 2 * @ z' lavorare sopra è solo una felice coincidenza. – Arjan

risposta

19

MySQL documentation è abbastanza chiaro su questo:

Come regola generale, 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 della valutazione per le espressioni che coinvolgono variabili utente non è definito e può cambiare in base agli elementi contenuti in una determinata istruzione; inoltre, questo ordine non è garantito per essere lo stesso tra le versioni del server MySQL. In SELECT @a, @a: = @ a + 1, ..., potresti pensare che MySQL valuterà prima @a e poi eseguirà un incarico secondo. Tuttavia, la modifica dell'istruzione (ad esempio, aggiungendo una clausola GROUP BY, HAVING o ORDER BY) può causare a MySQL di selezionare un piano di esecuzione con un diverso ordine di valutazione.

Si può fare ciò che si desidera utilizzare una sottoquery:

select @z, @z*2 
from (SELECT @z:=sum(item) 
     FROM TableA 
    ) t; 
+3

La query è piuttosto complicata, quindi non voglio aggiungere più sottoquery. E perché sta lavorando con le procedure? L'utilizzo di una variabile sulla procedura è molto più rapido rispetto all'utilizzo della procedura due volte. Quindi non capisco, perché questo non dovrebbe funzionare anche con la somma (articolo). – user2370579

+0

Ma la sottoselezione fa parte dell'istruzione select, quindi anche il tuo suggerimento non è definito. – philipxy

+0

@philipxy. . . La sottoquery viene eseguita prima della query esterna, quindi l'ordine è definito. –

4

Lavori in mysql 5,5

select @code:=sum(2), 2*@code 

+---------------+---------+ 
| @code:=sum(2) | 2*@code | 
+---------------+---------+ 
|    2 |  4 | 
+---------------+---------+ 
+7

No, questo non funziona nella mia installazione di MySQL 5.6; la seconda colonna restituisce 'NULL' alla prima invocazione e restituisce 2 volte * il risultato precedente * se viene eseguito di nuovo, il che potrebbe ingannare uno nel pensare che abbia funzionato. Ora, abbastanza interessante, sia 'select @code: = 2, 2 * @ code' e' select @code: = rand(), 2 * @ code; '* do * funziona nella stessa installazione (oggi). Quindi, data la documentazione (vedi la risposta di Gordon), non mi fiderei di questo per restituire qualche risultato definito. – Arjan

0
mysql> select @z := sum(5), if(@z := sum(5), 2*@z, 0) ; 
+--------------+------------------------------+ 
| @z := sum(5) | if(@z := sum(5), 2*@z, null) | 
+--------------+------------------------------+ 
|   5 |       10 | 
+--------------+------------------------------+ 

Credo che avvolgendo la 2*@z nella dichiarazione if garantirà la sum viene eseguito PRIMA del calcolo aggiuntivo.

+2

Che senso ha assegnare a '@ z' se si sta eseguendo lo stesso calcolo in entrambi i punti in cui' @ z' è usato ?! –