2011-08-29 16 views
7

Nel mio sistema, ho clienti. I clienti hanno programmi. Voglio visualizzare un elenco di client, mostrando il loro programma attivo più recente (se esiste).Ordine entro gruppo da?

Così, abbiamo qualcosa di simile:

SELECT * 
FROM clients AS client 
    JOIN programs AS program ON client.id=program.client_id 
GROUP BY client.id 
ORDER BY program.close_date=0 DESC, program.close_date DESC 

close_date=0 significa che il programma non è chiuso. Quindi metterà prima i programmi non chiusi e poi quelli chiusi più di recente.

Il problema è che l'ordine non funziona all'interno dei gruppi. È solo una specie di scegliere uno dei programmi a caso. Come posso risolvere questo?


appena arrivato fino a questo:

SELECT * 
FROM clients AS client 
    JOIN (SELECT * FROM programs AS program ORDER BY program.close_date=0 DESC, program.close_date DESC) AS program ON client.id=program.client_id 
GROUP BY client.id 

che sembra dare risultati corretti. È corretto, o sto solo diventando fortunato? cioè, ho essenzialmente ordinato il tavolo prima di unirlo; quei risultati rimarranno ordinati come fa il join, giusto?


Soluzione: ora credo questo un classico group-wise maximum problema. Cercalo se sei bloccato su un problema simile. La soluzione prevede di unire due volte lo stesso tavolo.

+3

L'ordine BY nella sottoselezione non dovrebbe avere alcun effetto deterministico sul risultato. Potrebbe succedere di lavorare con MySQL, ma lo standard SQL non lo consente nemmeno. Il punto chiave è ordinare il client.id nella principale (query esterna), quindi in qualsiasi altra colonna desiderata. Potresti dover dire le stesse cose nelle clausole GROUP BY e ORDER BY; non costa nulla per farlo. –

+2

@Mark: Non penso che la tua soluzione alternativa (pubblicata sopra) possa garantire risultati corretti. Dopo che un 'GROUP BY' è stato eseguito su' client.id', ["il server è libero di scegliere qualsiasi record da ciascun gruppo"] (http://dev.mysql.com/doc/refman/5.0/en/group -da-nascosto-columns.html). – unutbu

+0

@ubutbu: Grazie! Questo è esattamente quello che volevo sapere. Ero preoccupato che potesse essere il caso. – mpen

risposta

7
SELECT c.*, p.* 
FROM clients AS c 
JOIN programs AS p 
ON  p.id = 
     (
     SELECT pi.id 
     FROM programs AS pi 
     WHERE pi.client_id = c.id 
     ORDER BY 
       pi.close_date=0 DESC, pi.close_date DESC 
     LIMIT 1 
     ) 

Grazie dovrebbe andare a @Quassnoi. Vedere la sua risposta in un simile (ma più complicato) domanda: mysql-group-by-to-display-latest-result


Se si aggiorna la tabella programs e impostare close_date per tutti i record che è zero a close_date='9999-12-31', allora il vostro ORDER BY sarà più semplice (e l'intera query più veloce con indici appropriati):

 ORDER BY 
       pi.close_date DESC 
+0

Ah ... sì, questo join ha molto più senso. Molte grazie! – mpen

+0

Questa è la risposta che ho cercato ovunque. – atomkirk

1

Prova questo ordine dalla clausola ...

ORDER BY client.id, CASE WHEN program.close_date = 0 THEN 0 ELSE 1 END, program.close_date DESC 
+0

Non vedo come ciò possa portare a qualcosa. 'program.close_date = 0' valuterà a' 0' o '1' già. Il problema è che ho bisogno di ordinare all'interno dei gruppi, l'ordinamento globale (dopo il raggruppamento) va bene. – mpen

+2

La prima colonna elencata è client.id ... che manterrà i tuoi gruppi insieme. – JSR

+0

Oh ..... dovresti averlo indicato nella tua risposta. Anche se non sono ancora sicuro al 100% di cosa intendi. Mettere 'client.id' prima farà sì che l'ordinamento funzioni? Perché farebbe la differenza? – mpen