DECLARE @NumberOfRows INT ,@FStartValue FLOAT ,@FEndValue FLOAT ,@FRange FLOATSELECT @NumberOfRows = 10000-- -- Random FLOATs on the closed interval {275, 850} ,@FStartValue = 275 ,@FEndValue = 850 ,@FRange = @FEndValue - @FStartValueDECLARE @MyTestTable TABLE ( RandomFloat FLOAT)INSERT INTO @MyTestTableSELECT TOP (@NumberOfRows) RandomFloat = RAND(CHECKSUM(NEWID())) * @FRange + @FStartValue FROM sys.all_columns a1 CROSS JOIN sys.all_columns a2

declare @bins as int = 40declare @interval as floatdeclare @min as floatdeclare @max as floatselect @interval = (max(RandomFloat) - min(RandomFloat))/@bins, @min = min(RandomFloat), @max = max(RandomFloat)from @MyTestTable;with cteHistogram (N, StartBin, EndBin, TotalCount)as( select N, @min+(@interval*(N-1)) StartBin, @min+(@interval*N) EndBin, coalesce(count(RandomFloat), 0) TotalCount from @MyTestTable cross join Tally where RandomFloat >= @min+(@interval*(N-1)) and RandomFloat < @min+(@interval*N) and n <= @bins-1 group by N union all select N, @min+(@interval*(N-1)) StartBin, @min+(@interval*N) EndBin, coalesce(count(RandomFloat), 0) TotalCount from @MyTestTable cross join Tally where RandomFloat >= @min+(@interval*(N-1)) and RandomFloat <= @max and n = @bins group by N)select Tally.N, @min+(@interval*(Tally.N-1)) StartBin, case when Tally.N = @bins then @max else @min+(@interval*Tally.N) end EndBin, coalesce(TotalCount, 0) TotalCountfrom Tally left outer join cteHistogram on Tally.N = cteHistogram.Nwhere Tally.N <= @binsorder by Tally.N

;with cteHistogram (N, StartBin, EndBin, TotalCount)as( select N, @min+(@interval*(N-1)) StartBin, @min+(@interval*N) EndBin, coalesce(count(RandomFloat), 0) TotalCount from @MyTestTable cross join Tally where RandomFloat >= @min+(@interval*(N-1)) and ((RandomFloat < @min+(@interval*N) and n <= @bins-1) OR (RandomFloat <= @max and n = @bins)) group by N)select Tally.N, @min+(@interval*(Tally.N-1)) StartBin, case when Tally.N = @bins then @max else @min+(@interval*Tally.N) end EndBin, coalesce(TotalCount, 0) TotalCountfrom Tally left outer join cteHistogram on Tally.N = cteHistogram.Nwhere Tally.N <= @binsorder by Tally.N

--------------------------------------------------------------------------- calculate the range start and end for each bin;WITH Bins AS ( SELECT t.n, RangeStart = minval + (interval * (t.n-1)), RangeEnd = CASE WHEN t.n = @bins THEN maxval+1 ELSE minval + (interval * t.n) END FROM ( SELECT interval = (MAX(RandomFloat) - MIN(RandomFloat)) / @bins, minval = MIN(RandomFloat), maxval = MAX(RandomFloat) FROM @MyTestTable ) d CROSS JOIN Tally t WHERE t.n <= @bins)-- Summarise the bin contents. Min and max are actual bins.SELECT b.N, StartBin = MIN(RandomFloat), EndBin = MAX(RandomFloat), RangeStart = MIN(b.RangeStart), RangeEnd = MIN(b.RangeEnd), TotalCount = COUNT(*) FROM Bins bINNER JOIN @MyTestTable t ON t.RandomFloat >= b.RangeStart AND t.RandomFloat < b.RangeEndGROUP BY N

-- split the set into (@bins) roughly equal-sized populations SELECT N, StartBin = MIN(RandomFloat), EndBin = MAX(RandomFloat), TotalCount = COUNT(*)FROM ( SELECT RandomFloat, N = NTILE(@bins) OVER(ORDER BY (RandomFloat)) FROM @MyTestTable) dGROUP BY N