2010-03-26 31 views
150

¿Puedo ejecutar una declaración de selección y obtener el número de fila si los artículos están ordenados?MySQL - Obtenga el número de fila en seleccionar

Tengo una tabla como la siguiente:

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

Entonces puede ejecutar esta consulta para obtener el número de pedidos por ID:

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

Esto me da un recuento de cada itemID en el tabla como esta:

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

Quiero obtener el número de fila también, así que podría decir que itemID=388 es la primera fila, 234 es el segundo, etc. (esencialmente el ranking de los pedidos, no solo un conteo sin procesar). Sé que puedo hacer esto en Java cuando recupero el resultado, pero me preguntaba si había una forma de manejarlo puramente en SQL.

actualización

Ajuste del rango agrega al conjunto de resultados, pero no ordena correctamente:

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

Para referencia futura: si desea ordenar desde el rango 1 al rango 5, use 'ORDER BY rank ASC' (ordenar por rango en ASC orden de venta). Supongo que eso es lo que quieres decir con * pero no ordenado correctamente * – GroundZero

+0

Posible duplicado de [ROW \ _NUMBER() en MySQL] (http://stackoverflow.com/questions/1895110/row-number-in-mysql) –

Respuesta

147

Tome un vistazo a this.

cambiar la consulta a:

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

Eso agrega el rango al conjunto de resultados, pero no los coloca en el orden correcto - pregunta actualizada con resultados – George

+1

Trate de mantener el 'ORDER BY ordercount DESC', y luego envuelva toda la consulta en otro' SELECT' que obtiene todo del primero, pero ordena por la columna de rango (0 en este caso). –

+1

¿Puedes mostrar un ejemplo de esto? ¿Cómo envolvería los seleccionados? – George

9

Se puede utilizar una variables de MySQL para hacerlo. Algo así debería funcionar (aunque son dos consultas).

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

Cuidado, esto no funcionaría porque 'order by' sucede ** después de ** la variable' @ x' ha sido evaluada. Intente experimentar ordenando usando las otras columnas. También experimenta con ambos 'desc' y' asc'. Verá que muchas veces fallan y las únicas veces que funciona es ** pura suerte ** debido al orden de su "selección" original que tiene el mismo orden que el orden de "orden por". Ver mi solución y/o la solución de Swamibebop. – Pacerier

+0

@Pacerier ¿estás seguro de eso? He agotado una consulta similar en un ejemplo diferente (básicamente, selecciono de la columna de números y los numere de acuerdo con su orden) al parecer, si pedí por var/row num, cuando cambió el orden de las filas resultantes, pero cada número tenía la misma fila num. Pero si ordeno por la columna de número, entonces 'ASC' /' DESC' cambiaría el orden en que esos números estaban numerados (de menor a mayor o viceversa). Entonces parece que en ese caso 'orden por' fue evaluado primero. –

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

Gracias por aclarar, esto resolvió el problema fuera de orden que estaba teniendo. – thaddeusmt

+1

Gracias, esto fue realmente útil para mí :) Estoy sorprendido de que no haya una manera más directa de obtener "índices" de filas de un conjunto de resultados ... pero de todos modos, gracias, esto fue útil. – rat

+0

Puede agregar una cuarta fila con una cuenta total incremental cambiando la primera instrucción de selección en SELECT \ @rn: = \ @ rn + 1 AS rank, itemID, ordercount, \ @tot: = \ @ tot + ordercount como totalcount. Para definir el valor inicial de \ @tot, esto se debe agregar después de t2: (SELECT \ @tot: = 0) t3. Elimine el \ before every \ @, que tuve que usar para eludir el formateo de mini-Markdown. –

21

solución de Swamibebop funciona, pero aprovechando table.* sintaxis, podemos avoid repeating los nombres de las columnas del interior select y obtener un resultado más simple/corto:

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

    /* your original select statement goes in here */ 

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

Así eso le 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

Esto funcionó como un campeón de lo que estaba necesitando. ¡Gracias! – user2020930

+0

¡Gracias! ejecutarlo bastante bien! ¡Gracias! –

+0

¿Sabe por casualidad por qué se usa '@r: = @r + 1' en una instrucción de selección, pero si está en un procedimiento almacenado con' declare r int; establecer r = 0; ', se queja (en' r: = r + 1')? –

Cuestiones relacionadas