Reputation: 2863
select
floor(value / 5) * 5 as binned_value,
count(*) as qty
from
myTable
group by
binned_value;
| id | value|
|----|------|
| 1 | 0 |
| 2 | 4 |
| 3 | 3 |
| 4 | 12 |
| binned_value | qty |
|--------------|-----|
| 0 | 3 |
| 10 | 1 |
Which means there are 3 value between 0..5 and 1 value between 10..15.
I want the output to be this:
| binned_value | qty |
|--------------|-----|
| 0 | 3 |
| 5 | 0 |
| 10 | 1 |
That is, I want any bin that has 0 qty to also be shown.
I know I can do this with a bunch of joins and unions, but 5
, the bin size, is a parameter.
It is possible to know beforehand the highest possible value.
Upvotes: 0
Views: 231
Reputation: 48197
Here I check what is the max value in myTable to create the bin list first
Here is the sqlFiddle DEMO
;WITH n(n) AS
(
SELECT 0
UNION ALL
SELECT n + 5
FROM n
WHERE n + 5 < ( select m.Value
from
myTable m
where not exists (select Value
from mytable t
where m.Value < t.Value
)
)
),
CTE as
(
select
floor(value / 5) * 5 as binned_value,
count(*) as qty
from
myTable
group by
floor(value / 5) * 5
)
SELECT n AS binned_value,
ISNULL(qty,0) AS qty
FROM
n LEFT JOIN
CTE on n.n = CTE.binned_value
OPTION (MAXRECURSION 1000);
Upvotes: 1
Reputation: 389
You could use recursive CTE to get multiples of 5 (in the example below II got 15, but you could increase it to whatever). Then make your query a subquery and join to it.
WITH NumbersByFive AS
(
SELECT n = 0
UNION ALL
SELECT n + 5 FROM NumbersByFive WHERE n <= 15
)
SELECT nbf.n AS binned_value,
ISNULL(qty,0) AS qty
FROM
NumbersByFive nbf
LEFT JOIN
(
select
floor(value / 5) * 5 as binned_value
,count(*) as qty
from myTable b
group by floor(value / 5) * 5
) Subqry
ON nbf.n = Subqry.binned_Value
Upvotes: 1