Leg*_*end 74 mysql histogram binning
有没有办法在MySQL中指定bin大小?现在,我正在尝试以下SQL查询:
select total, count(total) from faults GROUP BY total;
Run Code Online (Sandbox Code Playgroud)
正在生成的数据足够好,但行数太多.我需要的是一种将数据分组到预定义箱中的方法.我可以从脚本语言中做到这一点,但有没有办法在SQL中直接执行?
例:
+-------+--------------+
| total | count(total) |
+-------+--------------+
| 30 | 1 |
| 31 | 2 |
| 33 | 1 |
| 34 | 3 |
| 35 | 2 |
| 36 | 6 |
| 37 | 3 |
| 38 | 2 |
| 41 | 1 |
| 42 | 5 |
| 43 | 1 |
| 44 | 7 |
| 45 | 4 |
| 46 | 3 |
| 47 | 2 |
| 49 | 3 |
| 50 | 2 |
| 51 | 3 |
| 52 | 4 |
| 53 | 2 |
| 54 | 1 |
| 55 | 3 |
| 56 | 4 |
| 57 | 4 |
| 58 | 2 |
| 59 | 2 |
| 60 | 4 |
| 61 | 1 |
| 63 | 2 |
| 64 | 5 |
| 65 | 2 |
| 66 | 3 |
| 67 | 5 |
| 68 | 5 |
------------------------
Run Code Online (Sandbox Code Playgroud)
我在找什么:
+------------+---------------+
| total | count(total) |
+------------+---------------+
| 30 - 40 | 23 |
| 40 - 50 | 15 |
| 50 - 60 | 51 |
| 60 - 70 | 45 |
------------------------------
Run Code Online (Sandbox Code Playgroud)
我想这不能以直接的方式实现,但是对任何相关存储过程的引用也可以.
Jar*_*aro 148
这是一篇关于在MySQL中为数值创建直方图的超快速方法的帖子.
使用CASE语句和其他类型的复杂逻辑,还有多种其他方法可以创建更好,更灵活的直方图.这种方法一次又一次地赢得了我,因为它对于每个用例来说都很容易修改,而且简短而简洁.这是你如何做到的:
Run Code Online (Sandbox Code Playgroud)SELECT ROUND(numeric_value, -2) AS bucket, COUNT(*) AS COUNT, RPAD('', LN(COUNT(*)), '*') AS bar FROM my_table GROUP BY bucket;只需将numeric_value更改为您的列,更改舍入增量,就是这样.我已经使条形图处于对数刻度,因此当你有大的值时它们不会增长太多.
基于舍入增量,numeric_value应在ROUNDing操作中偏移,以确保第一个桶包含与后续桶一样多的元素.
例如,使用ROUND(numeric_value,-1),范围[0,4](5个元素)中的numeric_value将放置在第一个桶中,而[5,14](10个元素)放在第二个桶中,[15,24]放在第三个桶中,除非通过ROUND(numeric_value - 5,-1)适当地偏移numeric_value.
这是一些看起来非常甜的随机数据的查询示例.足以快速评估数据.
Run Code Online (Sandbox Code Playgroud)+--------+----------+-----------------+ | bucket | count | bar | +--------+----------+-----------------+ | -500 | 1 | | | -400 | 2 | * | | -300 | 2 | * | | -200 | 9 | ** | | -100 | 52 | **** | | 0 | 5310766 | *************** | | 100 | 20779 | ********** | | 200 | 1865 | ******** | | 300 | 527 | ****** | | 400 | 170 | ***** | | 500 | 79 | **** | | 600 | 63 | **** | | 700 | 35 | **** | | 800 | 14 | *** | | 900 | 15 | *** | | 1000 | 6 | ** | | 1100 | 7 | ** | | 1200 | 8 | ** | | 1300 | 5 | ** | | 1400 | 2 | * | | 1500 | 4 | * | +--------+----------+-----------------+一些注意事项:不匹配的范围不会出现在计数中 - 计数列中不会有零.另外,我在这里使用ROUND功能.如果您觉得它对您更有意义,您可以使用TRUNCATE轻松替换它.
我在这里找到了它http://blog.shlomoid.com/2011/08/how-to-quickly-create-histogram-in.html
Ber*_*Siu 27
Mike DelGaudio的回答就是我这样做的方式,但略有改变:
select floor(mycol/10)*10 as bin_floor, count(*)
from mytable
group by 1
order by 1
Run Code Online (Sandbox Code Playgroud)
优势?您可以根据需要制作大小的垃圾箱.100个箱子?floor(mycol/100)*100.5个箱子?floor(mycol/5)*5.
伯纳多.
Ofr*_*viv 16
SELECT b.*,count(*) as total FROM bins b
left outer join table1 a on a.value between b.min_value and b.max_value
group by b.min_value
Run Code Online (Sandbox Code Playgroud)
表格箱包含用于定义箱柜的列min_value和max_value.请注意,运算符"在x BETWEEN y和z上加入..."是包含的.
table1是数据表的名称
小智 11
Ofri Raviv的回答非常接近但不正确.该count(*)会是1即使有任何结果的直方图区间.需要修改查询以使用条件sum:
SELECT b.*, SUM(a.value IS NOT NULL) AS total FROM bins b
LEFT JOIN a ON a.value BETWEEN b.min_value AND b.max_value
GROUP BY b.min_value;
Run Code Online (Sandbox Code Playgroud)
select "30-34" as TotalRange,count(total) as Count from table_name
where total between 30 and 34
union (
select "35-39" as TotalRange,count(total) as Count from table_name
where total between 35 and 39)
union (
select "40-44" as TotalRange,count(total) as Count from table_name
where total between 40 and 44)
union (
select "45-49" as TotalRange,count(total) as Count from table_name
where total between 45 and 49)
etc ....
Run Code Online (Sandbox Code Playgroud)
只要没有太多的间隔,这是一个非常好的解决方案.
| 归档时间: |
|
| 查看次数: |
42951 次 |
| 最近记录: |