2010-03-26 12 views
150

Posso eseguire un'istruzione select e ottenere il numero di riga se gli elementi sono ordinati?MySQL - Ottieni il numero di riga su select

Ho una tabella come questa:

mysql> describe orders; 
+-------------+---------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+-------------+---------------------+------+-----+---------+----------------+ 
| orderID  | bigint(20) unsigned | NO | PRI | NULL | auto_increment | 
| itemID  | bigint(20) unsigned | NO |  | NULL |    | 
+-------------+---------------------+------+-----+---------+----------------+ 

posso quindi eseguire la query per ottenere il numero di ordini da ID:

SELECT itemID, COUNT(*) as ordercount 
FROM orders 
GROUP BY itemID ORDER BY ordercount DESC; 

Questo mi dà un conteggio di ogni itemID nel tabella come questa:

+--------+------------+ 
| itemID | ordercount | 
+--------+------------+ 
| 388 |   3 | 
| 234 |   2 | 
| 3432 |   1 | 
| 693 |   1 | 
| 3459 |   1 | 
+--------+------------+ 

voglio ottenere il numero di riga e, in modo potrei dire che itemID=388 è la prima riga, 234 è il secondo, ecc. (Essenzialmente la classifica degli ordini, non solo un conteggio grezzo). So che posso farlo in Java quando ottengo il risultato, ma mi chiedevo se c'era un modo per gestirlo esclusivamente in SQL.

Aggiornamento

Impostazione del rango aggiunge al set di risultati, ma non propriamente ordinato:

mysql> SET @rank=0; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT @rank:[email protected]+1 AS rank, itemID, COUNT(*) as ordercount 
    -> FROM orders 
    -> GROUP BY itemID ORDER BY rank DESC; 
+------+--------+------------+ 
| rank | itemID | ordercount | 
+------+--------+------------+ 
| 5 | 3459 |   1 | 
| 4 | 234 |   2 | 
| 3 | 693 |   1 | 
| 2 | 3432 |   1 | 
| 1 | 388 |   3 | 
+------+--------+------------+ 
5 rows in set (0.00 sec) 
+1

Per riferimento futuro: Se si desidera ordinare dal rango 1 al rango 5, utilizzare 'ORDER BY rango ASC '(ordinamento in base al rango in ordine crescente). Immagino che questo sia ciò che intendi per * ma non correttamente ordinato * – GroundZero

+0

Possibile duplicato di [ROW \ _NUMBER() in MySQL] (http://stackoverflow.com/questions/1895110/row-number-in-mysql) –

risposta

147

Date un'occhiata a this.

modificare la tua ricerca per:

SET @rank=0; 
SELECT @rank:[email protected]+1 AS rank, itemID, COUNT(*) as ordercount 
    FROM orders 
    GROUP BY itemID 
    ORDER BY ordercount DESC; 
+1

Che aggiunge il rango al set di risultati, ma non li mette nell'ordine corretto - domanda aggiornata con risultati – George

+1

Prova a mantenere l'ordine DESCRIZIONE ORDINA per, quindi avvolgi l'intera query in un altro 'SELECT' che ottiene tutto dal il primo, ma gli ordini dalla colonna del rango (0 in questo caso). –

+1

Puoi mostrare un esempio di questo? Come potrei avvolgere i selettivi? – George

9

è possibile utilizzare una delle variabili di MySQL per farlo. Qualcosa del genere dovrebbe funzionare (anche se sono due domande).

SELECT 0 INTO @x; 

SELECT itemID, COUNT(*) as ordercount, (@x:[email protected]+1) as rownumber FROM orders GROUP BY itemID ORDER BY ordercount DESC; 
+0

Attenzione, questo non funzionerebbe perché 'order by' succede ** dopo ** la variabile' @ x' è stata valutata. Prova a sperimentare ordinando utilizzando le altre colonne. Sperimenta anche con 'desc' e' asc'. Vedrai che molte volte falliranno e le uniche volte in cui funziona, è per ** pura fortuna ** a causa dell'ordine della tua "selezione" originale avente lo stesso ordine dell'ordine di "ordine per". Vedi la mia soluzione e/o la soluzione di Swamibebop. – Pacerier

+0

@Pacerier ne sei sicuro? Ho stancato una query simile in un altro esempio (fondamentalmente selezionare dalla colonna di numeri e numerarli in base al loro ordine) a quanto pareva che se avessi ordinato per var/row num, quando ha cambiato l'ordine delle righe risultanti, ma ogni numero aveva la stessa riga num. Ma se ordino secondo la colonna del numero, allora il 'ASC' /' DESC' cambierebbe l'ordine in cui quei numeri erano numerati (dal più piccolo al più grande o viceversa). In questo caso sembra che "order by" sia stato valutato per primo. –

157
SELECT @rn:[email protected]+1 AS rank, itemID, ordercount 
FROM (
    SELECT itemID, COUNT(*) AS ordercount 
    FROM orders 
    GROUP BY itemID 
    ORDER BY ordercount DESC 
) t1, (SELECT @rn:=0) t2; 
+0

Grazie per aver chiarito, questo ha risolto il problema fuori servizio che stavo vivendo. – thaddeusmt

+1

Grazie, è stato davvero utile per me :) Sono sorpreso che non ci sia un modo più semplice per ottenere "indici" di righe da un set di risultati ... ma comunque è stato utile. – rat

+0

È possibile aggiungere una quarta riga con un totale incrementale modificando la prima istruzione di selezione in SELECT \ @rn: = \ @ rn + 1 AS rank, itemID, ordercount, \ @tot: = \ @ tot + ordercount come totalcount. Per definire il valore iniziale di \ @tot questo dovrebbe essere aggiunto dopo il t2: (SELECT \ @tot: = 0) t3. Elimina \ prima di ogni \ @, che dovevo usare per aggirare la formattazione mini-Markdown. –

21

soluzione Swamibebop funziona, ma sfruttando table.* sintassi, siamo in grado di avoid repeating i nomi delle colonne della interno select e ottenere un più semplice/risultato più breve:

select @r := @r+1 , z.* from(

    /* your original select statement goes in here */ 

)z, (select @r:=0)y; 

Così che ti darà:

select @r := @r+1 , z.* from(

    select itemID, count(*) as ordercount 
    from orders 
    group by itemID 
    order by ordercount desc 

)z, (select @r:=0)y; 
+0

Questo ha funzionato come un campione per quello che mi serviva. Grazie! – user2020930

+0

Grazie! eseguilo abbastanza bene! Grazie! –

+0

Per caso sai perché usare '@r: = @r + 1' in un'istruzione select funziona, ma se è in una stored procedure con' declare r int; imposta r = 0; ', si lamenta (su' r: = r + 1')? –