【问题标题】:Mysql create freqency distributionMysql创建频率分布
【发布时间】:2013-02-09 22:07:42
【问题描述】:

我在下面有一个简单的表 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 个计数范围。

我不知道 #2 是否可以在单个选择中解决,但任何人都可以解决 #1 吗?

【问题讨论】:

  • 到目前为止,我在一次选择中找到了最小值和最大值,然后划分为 N 个范围,在 PHP 中构建了一个 SELECT 语句以编程方式创建范围,然后运行第二个选择。这并不能真正帮助任何人想出答案,但既然你问了。
  • 你能给出相同的样本数据和你想要的结果吗?
  • 如果bird_count = 200,它将在哪一行?
  • @Michelle 你的意思是在第 17 天统计了 0 到 99 只鸡,然后在另外 23 天统计了 100 到 199 只鸡,等等?
  • 是的 - 我已更新问题以反映非重叠范围

标签: mysql count distribution frequency


【解决方案1】:

我猜你的实际 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 轻松解决。

【讨论】:

    【解决方案2】:

    当创建这样的东西时,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”的存储桶中。

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

    【讨论】:

    • 您不知道鸟类的最高和最低数量,因此您的解决方案将创建大量范围(每个范围大小为 100)。
    • 并非如此,它只会为表中实际存在的值创建存储桶。
    【解决方案3】:
    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 您可以在子查询中找到。

    【讨论】:

    • 这看起来很有希望(尚未测试)。我假设 GROUP 将强制每个范围的计数总计(如 WHERE >=range_start 和
    • 如果在任何单个范围内都没有鸟类计数会怎样?我假设它不会创建一行输出(即没有鸟数为 0 的行)。
    • 不会。考虑一下您可以尝试使用外部连接,我将在几分钟内通过示例编辑答案。如果您需要动态范围数,则仅使用 sql 将很困难。
    • 经过几次尝试我没有找到解决这个问题的方法,我认为这是因为 bird_count 列用于计算范围和分组依据,所以如果一个范围没有行它可以' t 被计算。您需要检查代码中的空范围或使用固定范围。
    • 然后我会进行第二次选择 - 这似乎运作良好。谢谢
    【解决方案4】:

    以@gustek answer 和维基百科的Histogram 页面为基础,这里有几个解决方案,使用斯科特规则和赖斯规则,使用箱数公式动态设置箱宽 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 问题。

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 2016-01-04
      • 2011-02-05
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2015-09-07
      相关资源
      最近更新 更多