2013-08-16 9 views
5

Ho una domanda che danno risultato similequery MySQL ha bisogno di essere ottimizzato

id | productid | userid | coinsid 
1 | 2   | 2  | 5  
3 | 2   | 2  | 6  
4 | 2   | 3  | 7 
5 | 2   | 4  | 8 
6 | 2   | 3  | 9 

Questo è risultato alla sua specifica productid. Ora devo aggiornare il saldo in user table aggiungendo $ 1 a tutti gli utenti nel risultato sopra, ma se userid è due volte, ho bisogno di aggiungere $ 1 due volte al saldo di quell'utente specifico. Quindi nel caso precedente $ 1 aggiunto due volte al saldo userid=2 e al saldo userid=3.

Il modo semplice è contare i record per ogni distinto userid ed eseguire le interrogazioni quante volte abbiamo gli utenti nel ciclo foreach. Ma sto cercando un modo ottimale. Si prega di suggerire qualsiasi Grazie

+0

raggruppa i risultati della query per userID e somma coinsID aggiunge una colonna per il conteggio di userID moltiplica il conteggio di userID per il tuo $ 1 e aggiorna il coinsId con quel nuovo valore. – xQbert

+0

@AliBZ, Sì 'saldo' è il nome della colonna nella tabella utente. Dove devo aggiornare il bilancio. –

+0

Mi dispiace, mio ​​male, ho perso quella parte. – AliBZ

risposta

4

Un approccio:

UPDATE user_table u 
    JOIN (SELECT q.userid 
       , SUM(1.00) AS deposit 
      FROM (
        -- original OP query goes here 
       ) q 
      GROUP BY q.userid 
     ) r 
    ON r.userid = u.userid 
    SET u.balance = u.balance + r.deposit 

Usiamo query OP originale che restituisce il gruppo di risultati visualizzata, e fare che un vista in linea (alias nella query precedente come q).

Da questo, si interroga un elenco distinto di ID utente e il numero di volte in cui l'ID utente viene visualizzato nel gruppo di risultati. Questo ci dà il nome utente e l'ammontare del deposito (1 dollaro per ogni volta che appare l'id utente) (alcuni database potrebbero volere che noi specifichiamo il valore come 1.0 anziché 1, per assicurarci che fosse decimale. Penso che la SUM sia più rappresentativa di ciò che stiamo cercando di realizzare.)

ci uniamo che vista in linea (r) alla tabella utente, e aggiungere l'importo del deposito al saldo corrente, per quell'utente (assumendo che il saldo viene archiviato come dollari decimali (1.00 = un dollaro)


Per il test, convertire il UPDATE in un SELECT dichiarazione:

  • rimuovere il "SET" clausola
  • aggiungere un "ORDER BY" clausola (opzionale) per rendere il risultati determinati
  • rimuovere la parola chiave "UPDATE" e sostituirla

con:

SELECT r.userid 
     , r.deposit 
     , u.balance    AS old_balance 
     , u.balance + r.deposit AS new_balance 
     , u.userid 
    FROM 

completa di selezione:

SELECT r.userid 
     , r.deposit 
     , u.balance    AS old_balance 
     , u.balance + r.deposit AS new_balance 
     , u.userid 
    FROM user_table u 
    JOIN (SELECT q.userid 
       , SUM(1.00) AS deposit 
      FROM (
        -- original OP query goes here 
       ) q 
      GROUP BY q.userid 
     ) r 
    ON r.userid = u.userid 

NOTA non c'è clausola WHERE, il predicati JOIN (nella clausola ON) è ciò che determina quali righe sono selezionate/interessato nella tabella utente.

+0

(mancava in precedenza i criteri di join ... DOH! Risolto. – spencer7593

+0

grazie per la risposta. L'ho provato, e ho aggiornato il bilancio per me ma purtroppo aggiornato per tutti gli utenti, abbiamo bisogno della clausola where alla fine della query di aggiornamento? –

+0

Ha funzionato perfettamente ora. Vorrei provare più utenti :) –

0
select count(*), userid from yourTable group by userid 

Se capisco la tua domanda.

1

Supponendo di avere alcun ID utente duplicati nella tabella equilibrio, forse qualcosa di simile a questo dovrebbe funzionare:

update balance_table set balance_table.balance = (select count(*) from users_table where users_table.user_id = balance_table.user_id) * 1; 

non ho provato questa query in un database mysql come io sono più familiarità con plsql, ma non sarebbe qualcosa come questo lavoro?

+0

Il * 1 in questo caso è perché si desidera aggiungere 1 $ per occorrenza dell'utente, ma potrebbe essere modificato in qualsiasi importo. – schwarz

+0

Non duplicato ma più userid, quindi non funzionerà credo. –

1

La sottoquery correlata nell'altra risposta funzionerà, ma un JOIN INNER di solito sarà più efficiente. Prova qualcosa come questo; ovviamente dovrai fornire i nomi delle tabelle e delle colonne.

UPDATE myTable 
INNER JOIN (
    SELECT userid, count(*) AS AmountToAdd 
    FROM users 
    GROUP BY userid 
) UserCounts ON myTable.userid = UserCounts.userid 
SET balance = balance + UserCounts.AmountToAdd 
+0

Questo è un approccio praticabile. Ma la vista in linea in questa query è 'FROM users', ma OP indica che l'elenco di utenti è il risultato di una query (non è stato fornito il testo effettivo della query.) Quindi OP dovrebbe sostituire' Dagli utenti '. con 'FROM (SELECT/* query originale * /) alias'. Ogni volta che c'è più di una tabella a cui fa riferimento in una query, è consigliabile qualificare TUTTI i riferimenti di colonna. – spencer7593

Problemi correlati