2010-04-07 17 views
9

Devo selezionare gli ultimi due record per ogni argomento.Come selezionare gli ultimi due record per ogni topic_id in MySQL

es: tabella: msg

id | topic_id 
------------ 
1 | 1 
2 | 1 
3 | 1 
4 | 1 
5 | 2 
6 | 2 
7 | 2 
8 | 3 
9 | 3 
10 | 3 

voglio ottenere questi file:

3 1 
4 1 
6 2 
7 2 
9 3 
10 3 

Come posso fare questo?

grazie

+0

ci sono scorciatoie che potremmo assumere? per esempio nei dati sopra riportati i tuoi ID stanno salendo senza buchi e per gli ID ascendenti hai anche topic_id crescente - se possiamo assumere che renderà la query più facile. un altro approccio potrebbe usare l'ipotesi che ci siano almeno due voci per ogni topic_id. possiamo supporre che? – Unreason

risposta

1

Si potrebbe

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT t.id 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id 
    ORDER BY t.id DESC 
    LIMIT 2) 
ORDER BY a.topic_id, a.id 

EDIT: Come sembra che MySQL non consente (! Ancora sarà possibile nelle prossime versioni) per utilizzare LIMIT in subquery Ecco una soluzione generalizzata (senza ipotesi scorciatoia, solo che msg.id è unico per topic_id):

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT MAX(t.id) 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id 
      ) OR 
     a.id IN (
    SELECT MAX(t.id) 
    FROM MSG t 
    WHERE a.topic_id = t.topic_id AND 
    t.id NOT IN (
     SELECT MAX(t2.id) 
     FROM MSG t2 
     WHERE t.topic_id = t2.topic_id 
       ) 
      )  
ORDER BY a.topic_id, a.id 

naturalmente questo non è bello, ma ci siete. Se si assume che gli ID di topic_id siano in ordine crescente senza buchi, è possibile apportare ulteriori miglioramenti alla query.

+0

mi dà il seguente errore "MySQL non supporta ancora 'LIMIT & IN/TUTTI/QUALSIASI/QUALCUNO subquery'" – Salil

+0

risposta aggiornata per compensare la limitazione di mysql di cui non ero a conoscenza. – Unreason

0

Mi piacerebbe sapere una risposta migliore per questa query, ma seguente funzionerà.

SELECT * FROM msg where id in (SELECT m.id FROM msg m group by topic_id) 
      or id in (SELECT m1.id FROM msg m1 where id not in (SELECT m2.id FROM msg m2 roup by topic_id) 
group by topic_id) order by id 
+0

in realtà non lo farebbe (c'è un errore di battitura mancante nella seconda sottoquery, cerca il roup), ma soprattutto - mysql non garantisce che il valore per le colonne non incluse nel gruppo provenga dall'ultimo record ed è libero di restituire qualsiasi valore che sceglie (o in altre parole, se la tua query restituisce i risultati desiderati, quindi per definizione è solo per coincidenza e potrebbe smettere di funzionare in qualsiasi momento) – Unreason

3

Un lavoro su SQL che non supporta il limite seguito dalla clausola IN è semplice. Costruisci un'altra subquery all'interno della tua clausola IN. Quindi per esempio.

SELECT a.id, a.topic_id 
FROM MSG a 
WHERE a.id IN (
    SELECT t.id 
    FROM (Select * from MSG t 
    WHERE a.topic_id = t.topic_id 
    ORDER BY t.id DESC 
    LIMIT 2)alias) 
ORDER BY a.topic_id, a.id 

Fammi sapere come funziona.

+0

Con questa query, ottengo l'errore "Colonna sconosciuta 'a.topic_id' in ' dove la clausola'" – rayne

3
SELECT max(id), max(topic_id) FROM msg 
GROUP BY topic_id 

UNION 

SELECT max(id), max(topic_id) FROM msg 
WHERE id not in (
    SELECT max(id) as id FROM msg 
    GROUP BY topic_id) 
GROUP BY topic_id 
Problemi correlati