Mysql
 sql >> Database >  >> RDS >> Mysql

Aiuto MySQL:ottimizza la query di aggiornamento che imposta il ranking in base all'ordine di un'altra colonna

Per prima cosa, cambierei budget , cost e rank_score in intero o altro tipo di dati numerico e invece di

UPDATE table_name
SET rank_score = CONCAT(cost, budget) ;

Quindi useresti:

UPDATE table_name
SET rank_score = cost * 1000 + budget * 1  ;

È più facile quindi perché non dovrai occuparti di funzioni di stringa e avere qualcosa come:

SELECT * 
FROM table_name
WHERE (conditions...)
ORDER BY rank_score DESC

(Tra parentesi:avere un parametro (1000 ) impostato così più alto dell'altro (1 ) equivale ad avere un ordine di cost, budget . Prova questo per controllare:

SELECT * 
FROM table_name
ORDER BY cost DESC
       , budget DESC

Quindi, puoi benissimo eliminare il rank_score nel complesso, a meno che, ovviamente, non prevediate di fare esperimenti con vari valori di parametro.

Come altri hanno sottolineato, non è consigliabile avere un campo che non memorizza dati ma un calcolo. È denormalizzazione. Invece, mantieni la tabella normalizzata e lasci che il database faccia i calcoli ogni volta che ne hai bisogno:

SELECT id, budget, cost, 
       cost*1000 + budget*1 AS rank_score_calculated
FROM table_name
ORDER BY rank_score_calculated DESC

rank_score_calculated non è memorizzato nell'esempio sopra. In questo modo, non dovrai aggiornare il campo calcolato ogni volta che viene modificato un budget o un costo o viene aggiunta una nuova riga nella tabella.

C'è solo un inconveniente. Se la tabella è davvero grande e hai bisogno di quella query (e del calcolo) eseguita da molti utenti e molto spesso, e la tabella viene aggiornata abbastanza spesso, allora potrebbe rallentare il tuo database. In tal caso, si dovrebbe iniziare a pensare di aggiungere un campo del genere.

L'altro caso è quando è necessario un rank assoluto su tutte le righe della tabella, come la tua esigenza. Poiché MySQL non ha funzioni di "finestra", è molto difficile scrivere una query del genere in puro SQL.)

Il rango può essere calcolato utilizzando le variabili MySQL

SELECT *
     , @rownum:[email protected]+1 AS rank_calculated
FROM table_name
   , (SELECT @rownum:=0) AS st
ORDER BY rank_score DESC

E se vuoi inserire quei valori in rank , usa:

UPDATE table_name
         JOIN
         ( SELECT id
                , @rownum:[email protected]+1 AS rank_calculated
           FROM table_name
              , (SELECT @rownum:=0) AS st
           ORDER BY rank_score DESC
         ) AS r
         ON r.id = table_name.id
SET table_name.rank = r.rank_calculated ;

Le due query precedenti non sono puro SQL. Puoi esaminare l'opzione per passare a un altro sistema di database che supporti le funzioni della finestra, come Postgres, SQL-Server o Oracle.