通过SQL获取价值分配

时间:2014-07-08 14:50:30

标签: mysql sql histogram

在MySQL数据库中,有一个包含单个数字value列的表。我想将这些值的分布绘制为条形图。图表中每个条形的宽度应均匀,每个条形的高度应反映此范围内的条目数。

例如,如果值的范围是-10..90且范围(条)的数量是10,那么图表中的第一个条应该显示范围-10..0中的条目数最后一个应该显示80..90范围内的条目数。

有没有比下面更好的方法来计算条形图数据:

  1. 使用select min(value), max(value) from mytable
  2. 获取最小值和最大值
  3. 计算每个范围的上限和下限(在应用程序代码中)
  4. 使用select count(*) from mytable where value between X and Y
  5. 获取每个范围内的值数

    这种简单方法的一个问题是需要发出单独的查询来查找每个范围内的值的数量,是否可以使其更有效,例如:通过动态构建查询并使用GROUP BY

3 个答案:

答案 0 :(得分:1)

SELECT * FROM my_table;
+----+-----+
| id | val |
+----+-----+
|  1 |  19 |
|  2 |  10 |
|  3 |   6 |
|  4 |  29 |
|  6 |  27 |
|  7 |  20 |
|  8 |  11 |
|  9 |  12 |
| 13 |  16 |
| 14 |  38 |
| 15 |   8 |
| 16 |  22 |
| 17 |  23 |
| 18 |  16 |
| 19 |  20 |
| 20 |  18 |
| 28 |  18 |
| 29 |   7 |
| 30 |  10 |
| 31 |  34 |
| 32 |  11 |
| 33 |  17 |
| 34 |  15 |
| 35 |  12 |
| 36 |  19 |
| 37 |  15 |
| 38 |  18 |
| 39 |  24 |
| 40 |  10 |
| 41 |  19 |
| 42 |  25 |
| 43 |  22 |
| 59 |  27 |
| 60 |  14 |
| 61 |  17 |
| 62 |  25 |
| 63 |  28 |
| 64 |  20 |
| 65 |  10 |
| 66 |  18 |
| 67 |  22 |
| 68 |  12 |
| 69 |  18 |
| 70 |  31 |
| 71 |  22 |
| 72 |  23 |
| 73 |  20 |
| 74 |  12 |
| 75 |  10 |
| 76 |   9 |
| 77 |  21 |
| 78 |  18 |
| 79 |  14 |
| 80 |  17 |
| 81 |   7 |
| 82 |  21 |
| 83 |  11 |
| 84 |  16 |
| 85 |  19 |
| 86 |  30 |
| 87 |  11 |
| 88 |  18 |
| 89 |  26 |
| 90 |  16 |
+----+-----+

SELECT CEILING(((1+val-(SELECT MIN(val) FROM my_table)))/ROUND((SELECT MAX(val)-MIN(val) FROM my_table)/8)) x
     , COUNT(*)
     , GROUP_CONCAT(LPAD(val,2,0) ORDER BY val) n
  FROM my_table
 GROUP
    BY CEILING(((1+val-(SELECT MIN(val) FROM my_table)))/ROUND((SELECT MAX(val)-MIN(val) FROM my_table)/8)); 
+------+----------+----------------------------------------------------+
| x    | COUNT(*) | n                                                  |
+------+----------+----------------------------------------------------+
|    1 |        5 | 06,07,07,08,09                                     |
|    2 |       13 | 10,10,10,10,10,11,11,11,11,12,12,12,12             |
|    3 |       11 | 14,14,15,15,16,16,16,16,17,17,17                   |
|    4 |       17 | 18,18,18,18,18,18,18,19,19,19,19,20,20,20,20,21,21 |
|    5 |        9 | 22,22,22,22,23,23,24,25,25                         |
|    6 |        5 | 26,27,27,28,29                                     |
|    7 |        2 | 30,31                                              |
|    8 |        1 | 34                                                 |
|    9 |        1 | 38                                                 |
+------+----------+----------------------------------------------------+

答案 1 :(得分:0)

SELECT CASE
WHEN (max(numb) - min(numb) BETWEEN xx AND yy THEN zz
WHEN (max(numb) - min(numb) BETWEEN zz AND aa THEN cc

将处理您的条形图的大小调整,而另一个查询中的GROUP BY将为您提供每个分布中的值。

答案 2 :(得分:0)

如果我正确理解您的问题,范围是未知的,您必须动态确定每个范围。像你一样找到最小值和最大值。使用游标计算每个范围的上限和下限,并将结果保存到包含 rangeLabel,lowerBound,upperBound 等字段的临时表中。选择临时表并使用子查询查找计数:

SELECT rangeLabel, (SELECT Count(*) FROM mytable 
    WHERE value BETWEEN temp.lowerBound AND temp.Upperbound) as myCount
FROM temp