Получение данных для построения гистограммы



есть ли способ указать размеры ячеек в 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 |
------------------------------


Я думаю, это не может быть достигнуто в прямом смысле, но ссылка на любую связанную хранимую процедуру также была бы прекрасна.

1085   10  

10 ответов:

Это пост о супер-быстрый-и-грязный способ создания гистограммы в MySQL для числовых значений.

есть несколько других способов создания гистограмм, которые лучше и более гибкий, используя операторы CASE и другие типы сложной логики. Этот метод побеждает меня снова и снова, так как это так просто чтобы изменить для каждого случая использования, и так коротко и лаконично. Вот как ты ... сделай это:

SELECT ROUND(numeric_value, -2)    AS bucket,
       COUNT(*)                    AS COUNT,
       RPAD('', LN(COUNT(*)), '*') AS bar
FROM   my_table
GROUP  BY bucket;

просто изменить numeric_value к чему бы ни была ваша колонка, измените округление приращения, и все. Я сделал решетку в логарифмическая шкала, так что они не растут слишком много, когда у вас есть большое значение.

numeric_value должно быть смещено в операции округления, на основе приращения округления, чтобы гарантировать, что первый блок содержит столько элементов, сколько следующие блоки.

например, с круглым (numeric_value, -1), numeric_value в диапазоне [0,4] (5 элементов) будет помещается в первое ведро, в то время как [5,14] (10 элементов) во втором, [15,24] в третьем, если numeric_value не смещается соответствующим образом через раунд(numeric_value - 5, -1).

Это пример такого запроса на некоторые случайные данные, что выглядит довольно сладкий. Достаточно хорошо для быстрой оценки данных.

+--------+----------+-----------------+
| bucket | count    | bar             |
+--------+----------+-----------------+
|   -500 |        1 |                 |
|   -400 |        2 | *               |
|   -300 |        2 | *               |
|   -200 |        9 | **              |
|   -100 |       52 | ****            |
|      0 |  5310766 | *************** |
|    100 |    20779 | **********      |
|    200 |     1865 | ********        |
|    300 |      527 | ******          |
|    400 |      170 | *****           |
|    500 |       79 | ****            |
|    600 |       63 | ****            |
|    700 |       35 | ****            |
|    800 |       14 | ***             |
|    900 |       15 | ***             |
|   1000 |        6 | **              |
|   1100 |        7 | **              |
|   1200 |        8 | **              |
|   1300 |        5 | **              |
|   1400 |        2 | *               |
|   1500 |        4 | *               |
+--------+----------+-----------------+

некоторые примечания: диапазоны, которые не совпадают, не будут отображаться в графе - у вас не будет нуля в столбце count. Кроме того, я использую Круглая функция здесь. Вы можете так же легко заменить его на усечение если вы чувствуете, что это имеет больше смысла для вас.

Я нашел его здесь http://blog.shlomoid.com/2011/08/how-to-quickly-create-histogram-in.html

Майк DelGaudio является, как я это делаю, но с небольшим изменением:

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.

Бернардо.

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 ....

пока не слишком много интервалов, это довольно хорошее решение.

Я сделал процедуру, которая может быть использована для автоматического создания временной таблицы для бункеров в соответствии с указанным числом или размером, для последующего использования с решением Ofri Raviv.

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

это создаст количество гистограмм только для заполненных ячеек. Дэвид Уэст должен быть прав в своей коррекции, но по какой - то причине незаселенные бункеры не появляются в результате для меня (несмотря на использование левого соединения-я не понимаю, почему).

Это должно сработать. Не так элегантно, но все же:

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

через Майк DelGaudio

select case when total >= 30 and total <= 40 THEN "30-40"       
       else when total >= 40 and total <= 50 then "40-50" 
       else "50-60" END as Total , count(total) 
group by Total 

в дополнение к большому ответу https://stackoverflow.com/a/10363145/916682, Вы можете использовать инструмент диаграммы phpmyadmin для хорошего результата:

enter image description here

enter image description here

равная ширина биннинга в заданное количество бункеров:

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 может быть десятичной).

Comments

    Ничего не найдено.