wm_concat Come selezionare 10 record sopra e sotto la riga secondo un doppio condizionale in SQL



wm_concat plsql (1)

Ho riscontrato un problema durante la creazione di una tabella dei punteggi più alti per la mia app.

Fondamentalmente, voglio essere in grado di interrogare un server (analisi) per 10 record sopra e sotto il record del punteggio più alto dell'utente e visualizzare qualcosa del genere:

  • 45 nome utente ...
  • 46 nome utente ...
  • 47 nome utente ...
  • 48 nome utente ...
  • 49 nome utente ...
  • 50 nome utente ...
  • 51 nome utente ...
  • 52 nome utente ...
  • 53 nome utente ...
  • 54 nome utente ...
  • 55 ALTO PUNTEGGIO DELL'UTENTE
  • 55 nome utente ...
  • 56 nome utente ...
  • 57 nome utente ...
  • 58 nome utente ...
  • 59 nome utente ...
  • 60 nome utente ...
  • 61 nome utente ...
  • 62 nome utente ...
  • 63 nome utente ...
  • 64 nome utente ...

Tecnicamente, non sto usando SQL, sto usando l'API Parse IOS. Ma la logica è la stessa quindi se riesco a capire come farlo in SQL, posso farlo usando l'API Parse.

Una soluzione apparentemente semplice sarebbe quella di trovare il punteggio più alto dell'utente ed eseguire una query per 10 record in cui il punteggio è maggiore di quello dell'utente e partecipare con una query per 10 record al di sotto dell'utente.

Questo non funziona perché quando due utenti hanno lo stesso punteggio elevato (questo accadrà spesso in questa app) voglio mostrare all'utente che ha ottenuto il punteggio più alto prima di essere sopra gli altri. Ad esempio, se Bill ha segnato 41 il 1 ° novembre e Bob ha segnato 41 il 2 novembre, Bill sarebbe sopra Bob nella classifica.

Le due colonne che sto usando per ordinare sono:

  • highScore: numero
  • createdAt: Date

Questo doppio condizionale è facile da implementare se trovo solo i primi 50 punteggi o qualcosa del genere ma non riesco a capire come centrare la query su un singolo record.

EDIT (la mia soluzione temporanea) Ho trovato una soluzione temporanea che funziona ma non è perfetta:

Dividi la query in 4 query:

  • q1: highScore> userScore; Descending-> highScore; Ascending-> createdAt; Limite 10
  • q2: highScore == userScore; createdAt <= userDate; Descending-> highScore; Ascending-> createdAt; Limite 10
  • q3: highScore == userScore; createdAt> userDate; Descending-> highScore; Ascending-> createdAt; Limite 10
  • q4: highScore <userScore; Descending-> highScore; Ascending-> createdAt; Limite 10

Quindi, se q2 restituisce meno di 10 record, riempire i restanti con q1. Se q3 restituisce meno di 10 record, riempilo con q4. Al massimo, questo restituisce solo 40 record per visualizzare 20, quindi questo funzionerà con query non molto sprecate.


In SQL, puoi farlo con un union tutti, prima di ottenere le 11 righe con punteggi più alti o uguali e poi le 10 righe con punteggi più bassi:

(select s.*
 from scores s
 where s.score >= (select max(score) from scores where user = $USER)
 order by s.score asc
 limit 11
)
union all
(select s.*
 from scores s
 where s.score <= (select max(score) from scores where user = $USER) and users <> $USER
 order by s.score desc
 limit 10
)




parse.com