如何计算数据范围内的行数?
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)
由于你的间隔是固定宽度的,你可以使用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 看看有什么不同。
我有一些数据,例如以下格式 分数数据范围从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)
由于你的间隔是固定宽度的,你可以使用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 看看有什么不同。