группа по диапазону в MySQL - PullRequest
15 голосов
/ 14 июля 2011
Table:   
new_table                                                    
user_number  | diff                  
     2       |  0                      
     1       |  28  
     2       |  32  
     1       |  40  
     1       |  53  
     1       |  59  
     1       |  101  
     1       |  105  
     2       |  108  
     2       |  129  
     2       |  130    
     1       |  144  


            |(result)
            v

range  | number of users  
0-20   |  2  
21-41  |  3  
42-62  |  1  
63-83  |  2  
84-104 |  1  
105-135|  0  
136-156|  3


select t.range as [range], count(*) as [number of users]  
from (  
  select case    
    when diff between 0 and 20 then ' 0-20'  
    when diff between 21 and 41 then ' 21-41'  
    when diff between 42 and 62 then ' 42-62'  
    when diff between 63 and 83 then ' 63-83'  
    when diff between 84 and 104 then ' 84-104'  
    when diff between 105 and 135 then ' 105-135'  
    else '136-156'   
     end as range  
  from new_table) t  
group by t.diff  

Error:

You have an error in your SQL syntax, near '[range], count(*) as [number of users]  
from (  
  select case  
    when' at line 1  

Ответы [ 8 ]

39 голосов
/ 02 ноября 2012

Вот общий код для группировки по диапазону, так как выполнение оператора case становится довольно громоздким.

Функция 'floor' может использоваться, чтобы найти нижнюю часть диапазона (не 'round', как использовал богемный), и добавить сумму (19 в примере ниже), чтобы найти верхнюю часть диапазона. Не забудьте не перекрывать нижнюю и верхнюю часть диапазонов!

mysql> create table new_table (user_number int, diff int);
Query OK, 0 rows affected (0.14 sec)

mysql>  insert into new_table values (2, 0), (1, 28), (2, 32), (1, 40), (1, 53),
        (1, 59), (1, 101), (1, 105), (2, 108), (2, 129), (2, 130), (1, 144);
Query OK, 12 rows affected (0.01 sec)
Records: 12  Duplicates: 0  Warnings: 0

mysql> select concat(21*floor(diff/21), '-', 21*floor(diff/21) + 20) as `range`,
       count(*) as `number of users` from new_table group by 1 order by diff;
+---------+-----------------+
| range   | number of users |
+---------+-----------------+
| 0-20    |               1 |
| 21-41   |               3 |
| 42-62   |               2 |
| 84-104  |               1 |
| 105-125 |               2 |
| 126-146 |               3 |
+---------+-----------------+
6 rows in set (0.01 sec)
8 голосов
/ 14 июля 2011

Вот решение, которое будет работать для любой величины разности:

select
  concat(21 * round(diff / 21), '-', 21 * round(diff / 21) + 20) as `range`,
  count(*) as `number of users`
from new_table
group by 1
order by diff;

Вот некоторый тестируемый код и его вывод:

create table new_table (user_number int, diff int);
insert into new_table values (2, 0), (1, 28), (2, 32), (1, 40), (1, 53), (1, 59), (1, 101), (1, 105), (2, 108), (2, 129), (2, 130), (1, 144); 
-- run query, output is: 
+---------+-----------------+
| range   | number of users |
+---------+-----------------+
| 0-20    |               1 |
| 21-41   |               1 |
| 42-62   |               2 |
| 63-83   |               2 |
| 105-125 |               3 |
| 126-146 |               2 |
| 147-167 |               1 |
+---------+-----------------+
6 голосов
/ 29 июля 2014

Если у вас есть регулярные диапазоны, более быстрое решение - сгруппировать с помощью функции div.

Например:

select diff div 20 as range, sum(user_number)
from new_table
group by diff div 20;

В этом случае диапазоны представлены как однозначные цифры, и вы должны знать, что они означают: 0 = 0-19, 1 = 20-39, 2 = 40-59, ...

Если вам нужны разные диапазоны, используйте другой делитель или, возможно, вычтите некоторое число из различий. Например, "(diff - 1) div 10" дает вам диапазоны 1-10, 11-20, 21-30, ...

6 голосов
/ 14 июля 2011

Mysql в качестве разделителя для ключевых слов использует знак обратной черты "` ", а не квадратные скобки (например, sql server)

1 голос
/ 06 августа 2015

диапазон - ключевое слово mysql. Вы должны «пересечь» это с помощью ´:

select t.`range` as [`range`], ...
0 голосов
/ 14 июля 2011

Возможно, вы захотите проверить Допустимы ли квадратные скобки в запросе SQL?

Я подозреваю, что '[' и ']' используются в SQL Microsoft, но не mysql.

0 голосов
/ 14 июля 2011
select 
case
when diff between 0 and 20 then ' 0-20'
when diff between 0 and 20 then ' 21-41'
when diff between 0 and 20 then ' 42-62'
when diff between 0 and 20 then ' 63-83'
when diff between 0 and 20 then ' 84-104'
when diff between 0 and 20 then ' 105-135'
else '136-156'
end; as 'range',
count(*) as 'number of users'


from new_table
group by range
0 голосов
/ 14 июля 2011

Одна очевидная ошибка: Mysql использует backticks (

`

), а не [] (как sqlserver). Изменить t.range as [range], count(*) as [number of users] на

t.range as `range`, count(*) as `number of users`
...