Есть ли способ указать размеры ящиков в MySQL? Прямо сейчас я пытаюсь выполнить следующий SQL-запрос:
select total, count(total) from faults GROUP BY total;
Генерируемые данные достаточно хороши, но строк слишком много. Что мне нужно, так это способ сгруппировать данные в заранее определенные ячейки. Я могу сделать это на языке сценариев, но есть ли способ сделать это непосредственно в SQL?
Пример:
+-------+--------------+
| total | count(total) |
+-------+--------------+
| 30 | 1 |
| 31 | 2 |
| 33 | 1 |
| 34 | 3 |
| 35 | 2 |
| 36 | 6 |
| 37 | 3 |
| 38 | 2 |
| 41 | 1 |
| 42 | 5 |
| 43 | 1 |
| 44 | 7 |
| 45 | 4 |
| 46 | 3 |
| 47 | 2 |
| 49 | 3 |
| 50 | 2 |
| 51 | 3 |
| 52 | 4 |
| 53 | 2 |
| 54 | 1 |
| 55 | 3 |
| 56 | 4 |
| 57 | 4 |
| 58 | 2 |
| 59 | 2 |
| 60 | 4 |
| 61 | 1 |
| 63 | 2 |
| 64 | 5 |
| 65 | 2 |
| 66 | 3 |
| 67 | 5 |
| 68 | 5 |
------------------------
Что я ищу:
+------------+---------------+
| total | count(total) |
+------------+---------------+
| 30 - 40 | 23 |
| 40 - 50 | 15 |
| 50 - 60 | 51 |
| 60 - 70 | 45 |
------------------------------
Я предполагаю, что это не может быть достигнуто прямым способом, но ссылка на любую связанную хранимую процедуру также будет хорошей.
Ответы:
Я нашел здесь http://blog.shlomoid.com/2011/08/how-to-quickly-create-histogram-in.html
источник
Майк ДельГаудио отвечает так, как я это делаю, но с небольшими изменениями:
select floor(mycol/10)*10 as bin_floor, count(*) from mytable group by 1 order by 1
Преимущество? Вы можете сделать мусорные ведра такими большими или маленькими, как захотите. Ящики размером 100?
floor(mycol/100)*100
. Ящики размером 5?floor(mycol/5)*5
.Бернардо.
источник
concat(floor(mycol/5)*5," to ",floor(mycol/5)*5+5)
round(mycol, -2)
из принятого ответа, поскольку он позволяет пользователю определять любой недесятичный «диапазон». Я бы просто использовалround
вместо,floor
поскольку он правильно округляет числа.SELECT b.*,count(*) as total FROM bins b left outer join table1 a on a.value between b.min_value and b.max_value group by b.min_value
Ячейки таблицы содержат столбцы min_value и max_value, которые определяют ячейки. обратите внимание, что оператор «соединить ... на x МЕЖДУ y и z» является включительным.
table1 - это имя таблицы данных
источник
Ответ Офри Равива очень близок, но неверен.
count(*)
Будет1
даже если есть нулевые результаты в интервале гистограммы. Чтобы использовать условное выражение, необходимо изменить запросsum
:SELECT b.*, SUM(a.value IS NOT NULL) AS total FROM bins b LEFT JOIN a ON a.value BETWEEN b.min_value AND b.max_value GROUP BY b.min_value;
источник
select "30-34" as TotalRange,count(total) as Count from table_name where total between 30 and 34 union ( select "35-39" as TotalRange,count(total) as Count from table_name where total between 35 and 39) union ( select "40-44" as TotalRange,count(total) as Count from table_name where total between 40 and 44) union ( select "45-49" as TotalRange,count(total) as Count from table_name where total between 45 and 49) etc ....
Пока интервалов не слишком много, это довольно хорошее решение.
источник
Я создал процедуру, которую можно использовать для автоматического создания временной таблицы для ящиков в соответствии с указанным числом или размером для дальнейшего использования с решением Офри Равива.
CREATE PROCEDURE makebins(numbins INT, binsize FLOAT) # binsize may be NULL for auto-size BEGIN SELECT FLOOR(MIN(colval)) INTO @binmin FROM yourtable; SELECT CEIL(MAX(colval)) INTO @binmax FROM yourtable; IF binsize IS NULL THEN SET binsize = CEIL((@binmax-@binmin)/numbins); # CEIL here may prevent the potential creation a very small extra bin due to rounding errors, but no good where floats are needed. END IF; SET @currlim = @binmin; WHILE @currlim + binsize < @binmax DO INSERT INTO bins VALUES (@currlim, @currlim+binsize); SET @currlim = @currlim + binsize; END WHILE; INSERT INTO bins VALUES (@currlim, @maxbin); END; DROP TABLE IF EXISTS bins; # be careful if you have a bins table of your own. CREATE TEMPORARY TABLE bins ( minval INT, maxval INT, # or FLOAT, if needed KEY (minval), KEY (maxval) );# keys could perhaps help if using a lot of bins; normally negligible CALL makebins(20, NULL); # Using 20 bins of automatic size here. SELECT bins.*, count(*) AS total FROM bins LEFT JOIN yourtable ON yourtable.value BETWEEN bins.minval AND bins.maxval GROUP BY bins.minval
Это сгенерирует счетчик гистограмм только для заполненных интервалов. Дэвид Уэст должен быть прав в своем исправлении, но по какой-то причине незаселенные корзины не отображаются в результате для меня (несмотря на использование LEFT JOIN - я не понимаю, почему).
источник
Это должно сработать. Не так изящно, но все же:
select count(mycol - (mycol mod 10)) as freq, mycol - (mycol mod 10) as label from mytable group by mycol - (mycol mod 10) order by mycol - (mycol mod 10) ASC
через Майка ДельГаудио
источник
SELECT CASE WHEN total <= 30 THEN "0-30" WHEN total <= 40 THEN "31-40" WHEN total <= 50 THEN "41-50" ELSE "50-" END as Total, count(*) as count GROUP BY Total ORDER BY Total;
источник
Биннинг одинаковой ширины в заданное количество бинов:
WITH bins AS( SELECT min(col) AS min_value , ((max(col)-min(col)) / 10.0) + 0.0000001 AS bin_width FROM cars ) SELECT tab.*, floor((col-bins.min_value) / bins.bin_width ) AS bin FROM tab, bins;
Обратите внимание, что 0,0000001 нужно для того, чтобы убедиться, что записи со значением, равным max (col), сами по себе не создают его собственной корзины. Кроме того, аддитивная константа предназначена для того, чтобы запрос не завершился ошибкой при делении на ноль, когда все значения в столбце идентичны.
Также обратите внимание, что количество бинов (10 в примере) должно быть записано с десятичной меткой, чтобы избежать целочисленного деления (нескорректированная bin_width может быть десятичной).
источник
WITH something AS
очень полезно, если вам нужно вычислить значение, которое попадает в ячейки.В дополнение к отличному ответу https://stackoverflow.com/a/10363145/916682 , вы можете использовать инструмент диаграммы phpmyadmin для хорошего результата:
источник