获取直方图的数据

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语句和其他类型的复杂逻辑,还有多种其他方法可以创建更好,更灵活的直方图.这种方法一次又一次地赢得了我,因为它对于每个用例来说都很容易修改,而且简短而简洁.这是你如何做到的:

SELECT ROUND(numeric_value, -2)    AS bucket,
       COUNT(*)                    AS COUNT,
       RPAD('', LN(COUNT(*)), '*') AS bar
FROM   my_table
GROUP  BY bucket;
Run Code Online (Sandbox Code Playgroud)

只需将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.

这是一些看起来非常甜的随机数据的查询示例.足以快速评估数据.

+--------+----------+-----------------+
| 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 | *               |
+--------+----------+-----------------+
Run Code Online (Sandbox Code Playgroud)

一些注意事项:不匹配的范围不会出现在计数中 - 计数列中不会有零.另外,我在这里使用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是数据表的名称

  • 为什么SQL的语法着色如此糟糕?我怎样才能改善这个?也许我应该把它发布在meta;) (2认同)
  • 在这种情况下,必须使用模板表来定义最小值.只有SQL才有可能. (2认同)

小智 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)


sam*_*mmy 9

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)

只要没有太多的间隔,这是一个非常好的解决方案.