2012-05-11 14 views
5

Sto cercando di eseguire alcuni calcoli all'interno di una query SELECT, utilizzando le variabili utente per farlo. Funziona bene fino a quando non utilizzo funzioni come SUM per raccogliere dati dalle tabelle unite.Variabili utente MySQL e funzione SUM

esempio semplificato:

SET @a = 1; 

SELECT @a := SUM(1 + 1) AS sum, @a 

Risultato:

+------+------+ 
| sum | @a | 
+------+------+ 
| 2 | 1 | 
+------+------+

mi aspetto di essere @a 2 qui.

Altro esempio:

SELECT @b := SUM(1 + 1) AS sum, @b; 
+------+------+ 
| sum | @b | 
+------+------+ 
| 2 | NULL | 
+------+------+

Ora è NULL, perché @b non è stato impostato prima che la query.

Sembra che la variabile non venga sovrascritta con il risultato della funzione SUM. C'è un modo per risolvere questo problema?

+0

cosa si vuole veramente ottenere –

+0

@AnkitSharma: calcoli all'interno di una query SELECT. Quindi ho bisogno di usare il risultato di ad es. 'SUM (1 + 1)' in ulteriori calcoli. Invece di usare 'SUM (1 + 1)' più e più volte, vorrei memorizzarlo in una variabile _ once_, ad es. '@ a', quindi riutilizzare' @ a' in seguito. – Alec

+0

usa 'SET @b = SUM (1 + 1)' –

risposta

5

Come dichiarato in the documentation:

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. In SELECT @a, @a:[email protected]+1, ..., si potrebbe pensare che MySQL valuterà prima @a e poi eseguirà un secondo. Tuttavia, la modifica dell'istruzione (ad esempio, aggiungendo una clausola o ORDER BY) può causare la scelta di un piano di esecuzione con un diverso ordine di valutazione da parte di MySQL.

Alla seconda parte della domanda. È possibile inizializzare il @variable all'interno di una query come questa (subqueries vengono valutate per prime):

SELECT @b := SUM(1 + 1) AS sum, @b FROM (SELECT @b:=0) b 
+0

Restituirà @b come 2? – Devart

+0

non garantito :) l'estratto dal documento che ho ri-pubblicato spiega perché. Basta non farlo così in una dichiarazione –

+0

Grazie, ho perso quella parte nei documenti. Ho pensato di risparmiarmi un po 'di tempo facendo calcoli nella query stessa, usando questi vars. Ma se i risultati sono incoerenti, non è davvero un'opzione. Dal momento che sto usando un sacco di variabili diverse, ciò significherebbe anche molte subquery, rendendole troppo complesse. Immagino che dovrò limitarmi a recuperare i dati principali con MySQL e usare PHP per fare i calcoli necessari in seguito. – Alec

1

E 'collegata alla valutazione delle espressioni. Nel tuo caso è possibile utilizzare un subquery -

SET @a = 1; 
SELECT sum, @a FROM 
    (SELECT @a := SUM(1 + 1) AS sum, @a) t 

+------+------+ 
| sum | @a | 
+------+------+ 
| 2 | 2 | 
+------+------+ 

Maggiori informazioni - User-Defined Variables.

Come regola generale, non è mai necessario 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.