2010-03-26 8 views
150

abrufen Kann ich eine SELECT-Anweisung ausführen und die Zeilennummer abrufen, wenn die Elemente sortiert sind?MySQL - Zeilennummer bei Auswahl

Ich habe eine Tabelle wie folgt aus:

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

dann kann ich diese Abfrage ausführen, um die Anzahl der Bestellungen von ID zu erhalten:

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

Das gibt mir eine Zählung jedes itemID in der Tabelle wie folgt:

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

Ich möchte die Zeilennummer auch erhalten, damit ich dassagen konnteist die erste Zeile, 234 ist zweite, usw. (im Wesentlichen die Reihenfolge der Aufträge, nicht nur eine rohe Anzahl). Ich weiß, dass ich dies in Java tun kann, wenn ich das Ergebnis zurückbekomme, aber ich frage mich, ob es einen Weg gibt, es rein in SQL zu handhaben.

aktualisieren

den Rang Einstellung fügt sie der Ergebnismenge, aber nicht richtig bestellt:

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

Für zukünftige Referenz: Wenn Sie von Rang 1 bis Rang 5 bestellen möchten, verwenden Sie 'ORDER BY Rang ASC' (Reihenfolge nach Rang in ASCending Reihenfolge). Ich denke das ist was du meinst mit * aber nicht richtig geordnet * – GroundZero

+0

Mögliches Duplikat von [ROW \ _NUMBER() in MySQL] (http://stackoverflow.com/questions/1895110/row-number-in-mysql) –

Antwort

147

bei this Werfen Sie einen Blick.

Ihre Suche verfeinern:

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

Das fügt den Rang zu der Ergebnismenge hinzu, bringt sie jedoch nicht in die richtige Reihenfolge - aktualisierte Frage mit Ergebnissen – George

+1

Versuchen Sie, die 'ORDER BY-Ordercount DESC 'zu behalten und dann die gesamte Abfrage in eine andere' SELECT' zu schreiben, die alles von der erster, aber Ordnungen durch die Rangspalte (0 in diesem Fall). –

+1

Können Sie ein Beispiel dafür zeigen? Wie würde ich die Selects verpacken? – George

9

Sie eine MySQL-Variablen, es zu tun verwenden können. So etwas sollte funktionieren (obwohl es zwei Abfragen sind).

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

Vorsicht, dies würde nicht funktionieren, weil 'order by' passiert ** nachdem ** die Variable' @x' ausgewertet wurde. Versuchen Sie zu experimentieren, indem Sie die anderen Spalten bestellen. Experimentieren Sie auch mit 'desc' und' asc'. Sie werden sehen, dass sie oft scheitern und nur wenn es funktioniert, ist es pures Glück ** aufgrund der Reihenfolge Ihres ursprünglichen "select" mit der gleichen Reihenfolge wie die Reihenfolge von "order by". Siehe meine Lösung und/oder Swamiibop's Lösung. – Pacerier

+0

@Pacierier bist du dir da sicher? Ich habe ähnliche Abfrage in einem anderen Beispiel müde (im Grunde wählen Sie aus der Spalte von Zahlen, und nummerieren sie nach ihrer Reihenfolge) bei schien es, dass, wenn ich von var/row num angeordnet, wenn es die Reihenfolge der resultierenden Zeilen geändert hat, aber jede Nummer hatte die gleiche Zeilennummer. Aber wenn ich nach der Zahlenspalte sortiere, würde die 'ASC' /' DESC' die Reihenfolge ändern, in der diese Nummern nummeriert wurden (vom kleinsten zum größten oder umgekehrt). Es sieht also so aus, dass in diesem Fall 'order by' zuerst ausgewertet wurde. –

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

Danke für die Klärung, das löste das Problem, dass ich außer Betrieb hatte. – thaddeusmt

+1

Danke, das war wirklich nützlich für mich :) Ich bin überrascht, dass es keine einfachere Möglichkeit gibt, Zeilen "Indizes" aus einem Ergebnissatz zu bekommen ... aber trotzdem, danke, das war praktisch. – rat

+0

Sie können eine vierte Zeile mit einem inkrementellen Totalcount hinzufügen, indem Sie die erste SELECT-Anweisung in SELECT \ @rn: = \ @ rn + 1 AS rank, itemID, ordercount, \ @tot: = \ tot + ordercount als Gesamtanzahl ändern. Um den Anfangswert von \ @tot zu definieren, sollte dies nach dem t2 hinzugefügt werden: (SELECT \ @tot: = 0) t3. Lösche das \ before every \ @, mit dem ich die Mini-Markdown-Formatierung umgehen konnte. –

21

Swamibebop-Lösung funktioniert, aber von Vorteile table.* Syntax nehmen, können wir die Spaltennamen der inneren select und ein einfacheres/kürzeres Ergebnis avoid repeating:

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

    /* your original select statement goes in here */ 

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

So das gibt dir:

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

Das funktionierte wie ein Champion für das, was ich brauchte. Vielen Dank! – user2020930

+0

Danke! mach es ganz gut! Vielen Dank! –

+0

Wissen Sie zufällig, warum die Verwendung von '@r: = @r + 1' in einer SELECT-Anweisung funktioniert, aber wenn es in einer gespeicherten Prozedur mit' declare r int; Setze r = 0; ', klagt es (auf' r: = r + 1')? –