如何计算数据范围内的行数?

how to count number of rows in a data range?

我有一些数据,例如以下格式 分数数据范围从1到100 以下是来自 table "ProductScore" 的数据,例如 附上图片和结果所需格式

我对SQL有点陌生 我觉得写查询很简单

你可以用 CASE:

;with cte AS (SELECT CASE WHEN Score <= 10 THEN '01: 1-10'
                          WHEN Score <= 20 THEN '02: 11-20'
                          ....
                          ELSE '10: 91-100'
                     END AS Ranges
                    ,ProductCode
              FROM ProductScore
             )
SELECT Ranges,COUNT(ProductCode)
FROM cte
GROUP BY Ranges
ORDER BY Ranges

注意:我为范围添加了前缀,以便可以按范围排序,您可以调整以适应。

我把它放在一个 cte 中,这样我就不必在 GROUP BY 中再次列出 CASE,正如 AlexPoole 所建议的,您可以添加另一个 CASE 用于订购并删除前缀:

;with cte AS (SELECT CASE WHEN Score <= 10 THEN '1-10'
                          WHEN Score <= 20 THEN '11-20'
                          ....
                          ELSE '91-100'
                     END AS Ranges
                     CASE WHEN Score <= 10 THEN 1
                          WHEN Score <= 20 THEN 2
                          ....
                          ELSE 10
                     END AS RangeOrder
                    ,ProductCode
              FROM ProductScore
             )
SELECT Ranges,COUNT(ProductCode)
FROM cte
GROUP BY Ranges
ORDER BY RangeOrder

假设您想要 10 的范围,您可以将 score 除以 10,然后按向下舍入的值分组

select to_char(floor("Score"/10)*10+1) || '-' || to_char(floor("Score"/10)*10+10),
count(*) 
from Table1
group by floor("Score"/10)
order by floor("Score"/10)

http://sqlfiddle.com/#!4/df1088/8

由于你的间隔是固定宽度的,你可以使用Oracle的nice函数WIDTH_BUCKET来达到你想要的结果:

SELECT (wb-1)*10+1 || '-' || wb*10 "DataRange" , COUNT(*) FROM ( 

  SELECT WIDTH_BUCKET("Score",1,100,10) wb
  --     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  --    divide the [1..100] range in 10 buckets of the
  --    same size
  FROM ProductScore

) V
GROUP BY wb
ORDER BY wb

查看 http://sqlfiddle.com/#!4/91e85/6 示例


此外,如果您需要显示甚至没有任何数据的桶,您可能需要添加一个外连接并更改 COUNT 函数:

SELECT (wb-1)*10+1 || '-' || wb*10 "DataRange" , COUNT("Score") FROM ( 
--                                               ^^^^^^^^^^^^^^
--                                       Count only row having a score
--                                       Can't use COUNT(*) here because
--                                       of the full outer join below

  SELECT WIDTH_BUCKET("Score",1,100,10) wb, "Score"
  FROM ProductScore

) V1

FULL OUTER JOIN (SELECT LEVEL wb FROM DUAL CONNECT BY LEVEL <= 10) V2
USING(wb)
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- always 10 buckets (from 1-10 to 91-100)


GROUP BY wb
ORDER BY wb;

看看 http://sqlfiddle.com/#!4/91e85/9 看看有什么不同。