Mysql创建频率分布

时间:2013-02-24 19:18:07

标签: mysql count distribution frequency

我在下面有一个简单的表BIRDCOUNT,显示在任何一天计算了多少只鸟:

+----------+
| NUMBIRDS |
+----------+
| 123      |
| 573      |
| 3        |
| 234      |
+----------+

我想创建一个频率分布图,显示计算了多少只鸟的次数。所以我需要MySQL来创建类似的东西:

+------------+-------------+
| BIRD_COUNT | TIMES_SEEN  |
+------------+-------------+
| 0-99       | 17          |
| 100-299    | 23          |
| 200-399    | 12          |
| 300-499    | 122         |
| 400-599    | 3           |
+------------+-------------+

如果鸟类数量范围得到修复,这将很容易。但是,我从来不知道看到多少只鸟的最小值/最大值。所以我需要一个选择语句:

  1. 创建与上述类似的输出,始终创建10个计数范围。
  2. (更高级)创建类似于上面的输出,始终创建N个计数范围。
  3. 我不知道在单个选择中是否可以使用#2但是任何人都可以解决#1?

4 个答案:

答案 0 :(得分:6)

SELECT
    FLOOR( birds.bird_count / stat.diff ) * stat.diff as range_start, 
    (FLOOR( birds.bird_count / stat.diff ) +1) * stat.diff -1 as range_end, 
    count( birds.bird_count ) as times_seen
FROM birds_table birds, 
    (SELECT 
        ROUND((MAX( bird_count ) - MIN( bird_count ))/10) AS diff
    FROM birds_table
    ) AS stat
GROUP BY FLOOR( birds.bird_count / stat.diff )

在这里你可以回答你的两个问题;]不同的是,范围的开始和结束是在单独的列而不是连接但是如果你在一列中需要它我想你可以从这里做到。 要更改范围数,只需编辑数字10您可以在子查询中找到。

答案 1 :(得分:1)

以@gustek answer和Wikipedia的Histogram页面为基础,这是使用Scott规则和Rice规则通过垃圾箱数量公式动态设置垃圾箱宽度h的几种解决方案, k = \ceil{ (max - min) / h }

# Histogram generator using Scott's rule, width(h) = (max - min) / k
SELECT any_value(FLOOR(r2.value / stat.width) * stat.width) as range_start,
       count(r2.value)                                      as times_seen,
FROM RESULT r2,
 (
     select 3.49 * stddev(r.value) / (power(count(*), 1 / 3)) as width
     from RESULT r
 ) as stat
GROUP BY FLOOR(r2.value / stat.width);

# Histogram using Rice rule k = ceil(2*n^1/3), width(h) = (max - min) / k
SELECT any_value(FLOOR(r2.value / stat.width) * stat.width) as range_start,
       count(r2.value)                                      as times_seen,
FROM RESULT r2,
 (
     select (max(r.value) - min(r.value)) / ceil(2 * power(count(*), 1 / 3)) as width
     from RESULT r
 ) as stat
GROUP BY FLOOR(r2.value / stat.width);

any_value()函数用于解决新的MySQL ONLY_FULL_GROUP_BY问题。

答案 2 :(得分:0)

我猜你的实际SQL查询:

SELECT dateColumn, COUNT(*) AS NUMBIRDS
FROM birdTable
GROUP BY dateColumn

如果是这样,你所要做的就是把你的计数“捏住”:

SELECT CONCAT_WS('-', 
   FLOOR( NUMBIRDS/100 )*100,
   ((FLOOR( NUMBIRDS/100 )+1)*100) - 1
) AS BIRD_COUNT
,COUNT(*) AS TIMES_SEEN
FROM (
    SELECT dateColumn, COUNT(*) AS NUMBIRDS
    FROM birdTable
    GROUP BY dateColumn
) AS birdCounts
GROUP BY BIRD_COUNT

当然,如果缺少其中一个范围,您将无法获得匹配的行 - 但如果这是一个问题,您可以通过LEFT JOIN轻松解决该问题。

答案 3 :(得分:0)

创建这样的东西时,GROUP BY是你的朋友。基本思想是将每个值放入一个桶中,然后计算每个桶中的元素数量。要创建存储桶,您可以定义一个函数,该函数获取值并计算存储桶的唯一值。

这样的事情:

SELECT
  @low := TRUNCATE(bird_count/100, 0) * 100 as Low,
  TRUNCATE(@low + 99, 0) as High,
  COUNT(*) AS Count
FROM birds_seen
GROUP BY Low;

在这种情况下,您可以定义一个捕获鸟计数的函数,并计算存储桶的较低范围。然后,您可以将较低范围内的所有值分组,例如,将123和145放入标记为“100”的桶中,将234和246放入标记为“200”的桶中。

现在,每个值都放在一个桶中,您可以按桶标签对值进行分组,并计算每个桶中的元素数。