计算值大于或等于SQL中另一列的值的行数

时间:2011-12-15 07:28:07

标签: sql database aggregate-functions aggregation

我有一个包含两列的表:一对id和一些“标记” 一对。我想要一个结果,其中列出了具有x标记的夫妻数量 或x的每个值的更多或更多。所以我的输入如下:

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

我想得到结果:

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

即。有一对夫妇有7个或更多的分数,3对夫妇有6个或更多的分数,4 有5个或更多分数的夫妇等我已经能够提出一个查询 返回完全 n标记的夫妻数量:

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

哪个收益率:

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

即。有1对夫妇有7个标记,2对夫妇有6个标记,1个有5个,等等 有一种方便的方法可以有效地将每行的值与上面的值相加 它?我可以在应用程序级别执行此操作,但它似乎就是这种情况 它真的属于数据库。

2 个答案:

答案 0 :(得分:7)

这可能不是特别有效,但应该完成工作:

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;

修改: 您可以在查询的select,from,where,group by和having子句中使用sub query,如果引用main / outer'query',那么它将评估每行的子查询,然后它是称为correlated subquery。 (因此关于表现的警告)

根据Damien的回答,你也可以使用CTE - CTE可以提高可读性,并且使IMO的递归和自连接变得更加容易。

大多数SQL都支持AFAIK子查询。

答案 1 :(得分:4)

您可以使用RANK()函数计算每个结果排名的位置,然后只需将绑定结果的数量添加到该排名中:

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

给出:

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

(7 row(s) affected)

(当然,如果您需要按特定顺序排列结果,请不要忘记添加ORDER BY条款 - 以上排序只是一个快乐的事故)