繁体   English   中英

MySQL:按值范围分组(从,到)

[英]MySQL: Group by range of values (From, To)

我正在寻找一种按范围对结果进行分组的方法。

例如:

数据:

ID | Value
1  |     5
2  |    10 
3  |    30
4  |    44
5  |    71 

结果:

|From  | To  | Count(*) |
|    0 |  20 |        2 |
|   20 |  40 |        1 |
|   40 |  60 |        0 |
|   60 |  80 |        1 |

我知道我可以很容易地在某种情况下或在查询的情况下执行此操作,但是我有几个表的范围存在很大差异(其中还包括十进制值),因此我希望找到一种能够自动在最小值和最大值之间创建20范围的解决方案最大值。

我找到了两个但无法适应的解决方案:

按价格范围进行分组 (非常相似,但它会根据值创建范围,因此永远不会有0个范围并且不会做整数)

按Year Band Interval对行进行分组 (我不熟悉发言权的使用,但这是我要完成的工作,但是我无法准确地计算行数)

非常感谢你的帮助

詹姆士

好吧,大声思考一下...

SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,Value INT NOT NULL
);

INSERT INTO my_table VALUES
(1  ,5),
(2  ,10),
(3  ,30),
(4  ,44),
(5  ,81),
(6  ,200),
(7, -200); 

SELECT a.*
     , COUNT(DISTINCT c.id) total
  FROM
     ( SELECT (i4.i*1000 + i3.i*100 + i2.i*10 + i1.i - 1000) * 20 `from`
            , ((i4.i*1000 + i3.i*100 + i2.i*10 + i1.i -1000) * 20) + 20 `to`
         FROM ints i1,ints i2, ints i3, ints i4
     ) a
  JOIN 
     ( SELECT MIN(value) min_val,MAX(value) max_val FROM my_table ) b
    ON b.max_val > a.from
   AND b.min_val < a.to
  LEFT
  JOIN my_table c
    ON c.value BETWEEN a.from AND a.to
 GROUP 
    BY a.from;
    +------+------+-------+
| from | to   | total |
+------+------+-------+
| -200 | -180 |     1 |
| -180 | -160 |     0 |
| -160 | -140 |     0 |
| -140 | -120 |     0 |
| -120 | -100 |     0 |
| -100 |  -80 |     0 |
|  -80 |  -60 |     0 |
|  -60 |  -40 |     0 |
|  -40 |  -20 |     0 |
|  -20 |    0 |     0 |
|    0 |   20 |     2 |
|   20 |   40 |     1 |
|   40 |   60 |     1 |
|   60 |   80 |     0 |
|   80 |  100 |     1 |
|  100 |  120 |     0 |
|  120 |  140 |     0 |
|  140 |  160 |     0 |
|  160 |  180 |     0 |
|  180 |  200 |     1 |
    +------+------+-------+

尽管我对性能没有任何正面保证,但可以这样做。

您需要找到上下边界。 可以通过获取最大值和最小值,将每个值除以20,使用floor / ceil将其取整,然后乘以20,然后将其与子查询交叉连接以生成一定范围的数字(以20s为单位)来完成。 确保此子查询具有足够大的范围(在下面的示例中,它正在生成1000个范围,因此最大值为0到20000)

这将为您提供所有范围。 您可以将实际数据连接起来,以计算每个范围内的实际值数。

请注意,示例范围从1到20,然后从20到40。因此,任何20值都将出现在2个范围内。 我假设0到但不包括20。 如果值是整数,则可以生成0-19、20-39等范围。

SELECT sub1.lower_boundary, sub1.upper_boundary, COUNT(value)
FROM
(
    SELECT FLOOR(MIN(value) / 20) * 20 AS min_boundary, CEIL(MAX(value) / 20) * 20 AS max_boundary
    FROM sometable
) sub0
CROSS JOIN
(
    SELECT (units.i + 10 * tens.i + 100 * hundreds.i) * 20 AS lower_boundary,(1 + units.i + 10 * tens.i + 100 * hundreds.i) * 20 AS upper_boundary
    FROM
    (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units,
    (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens,
    (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
) sub1
LEFT OUTER JOIN sometable a
ON a.Value >= sub1.lower_boundary
AND a.Value < sub1.upper_boundary
WHERE sub1.lower_boundary < max_boundary
AND  sub1.upper_boundary > min_boundary
GROUP BY sub1.lower_boundary, sub1.upper_boundary

SQL在这里摆弄:-

http://www.sqlfiddle.com/#!2/cd535/3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM