2011-12-15 14 views
5

Tengo una tabla con dos columnas: una identificación de pareja y una serie de "marcas" para esa pareja . Me gustaría obtener un resultado que enumere el número de parejas que tienen x marcas o más para cada uno de los valores de x. Así que mi entrada se parece a:Contando el número de filas con un valor mayor o igual a un valor de otra columna en SQL

 
| couple_id | num_marks | 
|-----------+-----------| 
|   9 |   7 | 
|   6 |   6 | 
|   8 |   6 | 
|   2 |   5 | 
|   3 |   4 | 
|   5 |   4 | 
|   1 |   3 | 
|   4 |   3 | 
|  10 |   2 | 
|   7 |   1 | 

Y me gustaría obtener el resultado:

 
| num_marks | num_couples | 
|-----------+-------------| 
|   7 | 1   | 
|   6 | 3   | 
|   5 | 4   | 
|   4 | 6   | 
|   3 | 8   | 
|   2 | 9   | 
|   1 | 10   | 

es decir, hubo 1 pareja con 7 o más marcas, 3 parejas con 6 o más marcas, 4 parejas con 5 o más marcas, etc. He podido hacer una consulta al devolver el número de parejas con exactamenten marcas:

SELECT num_marks, 
     count(couple_id) AS num_couples 
    FROM table_name 
    GROUP BY num_marks 
    ORDER BY num_marks DESC; 

que produce:

 
| num_marks | num_couples | 
|-----------+-------------| 
|   7 |   1 | 
|   6 |   2 | 
|   5 |   1 | 
|   4 |   2 | 
|   3 |   2 | 
|   2 |   1 | 
|   1 |   1 | 

Ie hubo 1 pareja con 7 marcas, 2 parejas con 6 marcas, 1 con 5, etc. ¿Hay una manera conveniente de sumar efectivamente el valor de cada fila con las de más de ? Puedo hacerlo a nivel de aplicación, pero parece ser el tipo de cosa que realmente pertenece a la base de datos.

Respuesta

5

Esto podría no ser particularmente eficaz, pero debe hacer el trabajo:

SELECT t1.num_marks,  
    (SELECT count(t2.couple_id) 
    FROM table_name t2 
    WHERE t2.num_marks >= t1.num_marks 
    ) AS num_couples 
FROM table_name t1 
GROUP BY t1.num_marks 
ORDER BY t1.num_marks DESC; 

Editar: Se puede utilizar un sub query en el selecto, desde donde, group by y tener cláusulas de una consulta , y si hace referencia a la 'consulta' principal/externa, entonces evaluará la subconsulta para cada fila, entonces se conoce como correlated subquery. (De ahí la advertencia sobre el rendimiento)

Según la respuesta de Damien, también podría usar un CTE - CTE puede mejorar la legibilidad y también hacer la recursión y autounirse mucho más fácil IMO.

Las subconsultas AFAIK son compatibles con la mayoría de los SQL.

+0

¡Eso es increíble! No sabía que podrías tener 'SELECT's como columnas. Es ese SQL estándar que funcionaría, p. SQLite y Postgres? Además, mi 'table_name' no es realmente una tabla, es un' SELECT' de bocinazo por sí mismo; ¿Eso rompería las cosas? – haxney

+1

@haxney - He editado - sí, puedes reemplazar table_name con otra consulta, necesitarás alias para usarlo en la selección externa. – StuartLC

4

Usted puede utilizar la función RANK() a calcular dónde cada resultado se ubica, a continuación, sólo tiene que añadir el número de resultados ligados a ese rango:

create table #T (couple_id int,num_marks int) 
insert into #T (couple_id,num_marks) 
select 9 ,   7 union all 
select 6 ,   6 union all 
select 8 ,   6 union all 
select 2 ,   5 union all 
select 3 ,   4 union all 
select 5 ,   4 union all 
select 1 ,   3 union all 
select 4 ,   3 union all 
select 10 ,   2 union all 
select 7 ,   1 

;with Ranked as (
    select num_marks,RANK() OVER (ORDER BY num_marks desc) as rk from #T 
) 
select num_marks,rk + COUNT(*) -1 as Result from Ranked 
group by num_marks,rk 

Da:

num_marks Result 
----------- -------------------- 
7   1 
6   3 
5   4 
4   6 
3   8 
2   9 
1   10 

(7 row(s) affected) 

(Por supuesto, si necesita los resultados en un orden en particular, no se olvide de agregar una cláusula ORDER BY - el orden anterior es solo un feliz accidente)

Cuestiones relacionadas