【问题标题】:Creating buckets to categorize the values using MySQL创建存储桶以使用 MySQL 对值进行分类
【发布时间】:2021-09-13 09:12:39
【问题描述】:

您好,我正在尝试为大量行创建存储桶。我的最大值为9759721,最小值为1006909。我想将结果显示如下:

distance bucket range
1006909 0 1000000 - 1009999
1013525 1 1010000 - 1019999
1021948 2 1020000 - 1029999

表格可能不太清楚,但总的来说,我想将它们分解为 10000 的变化。从1000000 开始,每10000 创建一个新桶。

我尝试了以下代码,但没有显示正确的输出。

select distance,floor(distance/10000) as _floor  from data;

我得到了类似的东西:

distance bucket
1006909 100
1013525 101
1021948 102
1035472 103
1042069 104
9759721 975

这似乎是正确的,但我需要存储桶从 0 开始,然后根据 10000 进行更改。然后还有一个范围列。我对距离的最小值是 1006909,因此数据不是从 0 开始的,但是仍然可以有一个从 0 开始的桶列[即分配给最小距离]。

【问题讨论】:

  • 您的存储桶确实从 0 开始,前提是您有 0 到 9999 之间距离的数据。如果您只想将存储桶 100 变为存储桶 0,只需从当前计算中减去 100?如果这不是您的意思,请用更多信息编辑您的答案? (另外,请说明您使用的 MySQL 版本。MySQL 8 和 MySQL 5.x 差别很大。)
  • @MatBailie 我刚刚编辑了标签,关于存储桶,我的最小值为 1006909,所以我的数据不是从 0 开始的。但是无论如何都不能从 0 或 1 开始存储桶您的数据从哪里开始?

标签: mysql sql bucket mysql-8.0


【解决方案1】:
SELECT
  d.distance,
  DENSE_RANK() OVER (ORDER BY d._floor) - 1  AS bucket,
  d._floor * 10000                           AS bucket_lower_limit,
  d._floor * 10000 + 10000                   AS bucket_upper_limit
FROM
(
  SELECT
    distance,
    FLOOR(distance / 10000)  AS _floor
  FROM
    data
)
  AS d

注意: 将给出从 0 向上编号的桶,但也会删除所有间隙 (这样您的样本数据将在最后一个桶 5行,而不是桶 975)

或者,如果您需要保留间隙...

SELECT
  d.distance,
  d._floor - MIN(d._floor) OVER ()   AS bucket,
  d._floor * 10000                   AS bucket_lower_limit,
  d._floor * 10000 + 10000           AS bucket_upper_limit
FROM
(
  SELECT
    distance,
    FLOOR(distance / 10000)  AS _floor
  FROM
    data
)
  AS d

【讨论】:

  • 嘿,我有一个案例,例如 1017743,upper bucket limit1020000,存储桶编号为 1,对于值 1021948,下限也是 1020000,存储桶编号为 2。现在,如果我的值正好是 1020000 会发生什么?它会去桶 1 还是桶 2
  • 这样的范围将被读作 Inclusive 用于下限和 Exclusive 为上限。以浮点值为例,你不会说from 1 to 1.9from 2 to 2.9,因为1.99 没有考虑到(你永远不够精确)。所以,你说from 1 to 2from 2 to 3,其中2 进入第二个桶。这个inclusive from, exclusive to 通常缩写为[1, 2)[2, 3)
【解决方案2】:

只需计算1006909 div 10000 * 10000 = 1000000 并从距离中减去它。这将使存储桶从 0 开始:

SELECT distance
     , (distance - a) div 10000 AS bucket
     , distance div 10000 * 10000 AS range_from
     , distance div 10000 * 10000 + (10000 - 1) AS range_to
FROM t
CROSS JOIN (
  SELECT MIN(distance) div 10000 * 10000 AS a
  FROM t
) AS x

SQL Fiddle

【讨论】:

  • 使用整数除法 (div) 很好,但为什么要使用子查询重新扫描数据呢?尤其是当MIN(x) OVER () 存在的时候?
猜你喜欢
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
相关资源
最近更新 更多