Frage

Gibt es eine Möglichkeit Behältergrößen in MySQL angeben? Gerade jetzt, ich versuche, die folgende SQL-Abfrage:

select total, count(total) from faults GROUP BY total;

Die Daten, die erzeugt wird, ist gut genug, aber es gibt einfach zu viele Zeilen. Was ich brauche, ist eine Möglichkeit, die Daten in vordefinierte Behälter zu gruppieren. Ich kann dies aus einer Skriptsprache, aber ist es eine Möglichkeit, sie direkt in SQL zu tun?

Beispiel:

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

Was ich suche:

+------------+---------------+
| total      | count(total)  |
+------------+---------------+
|    30 - 40 |            23 | 
|    40 - 50 |            15 | 
|    50 - 60 |            51 | 
|    60 - 70 |            45 | 
------------------------------

ich denke, das kann nicht in einer geradlinig Weise erreicht werden, sondern ein Hinweis auf eine im Zusammenhang gespeicherte Prozedur wäre auch in Ordnung sein.

War es hilfreich?

Lösung

  

Dies ist ein Beitrag über eine super-quick-and-dirty Weg, um ein Histogramm zu erstellen   in MySQL für numerische Werte.

     

Es gibt mehrere andere Möglichkeiten, Histogramme zu erstellen, die besser sind und   mit CASE-Anweisungen und andere Arten von komplexer Logik flexibler.   Diese Methode gewinnt mich im Laufe der Zeit immer wieder, da es nur so ist einfach   für jeden Anwendungsfall zu ändern, und so kurz und prägnant. Dies ist, wie Sie   es tut:

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

Just Änderung numeric_value, was auch immer Ihre Spalte, ändern Sie die   Rundungsschritt, und das ist es. Ich habe die Bars gemacht zu sein in   logarithmische Skala, so dass sie wachsen nicht zu viel, wenn Sie   große Werte.

     

numeric_value sollte in der Rundungsoperation ausgeglichen werden, basierend auf dem Rundungsschritt, um den ersten Eimer enthält so viele Elemente wie die folgenden Eimer zu gewährleisten.

     

z. mit ROUND (numeric_value, -1), numeric_value im Bereich [0,4] (5 Elemente) werden in ersten Eimer gelegt werden, während [5,14] (10 Elemente) in zweiten, [15,24] in dritten, es sei denn, numeric_value versetzt ist in geeigneter Weise über ROUND (numeric_value - 5, -1).

      Dies ist ein Beispiel für eine solche Abfrage auf einige zufällige Daten, die hübsch aussieht   Süss. Gut genug für eine schnelle Auswertung der Daten.

+--------+----------+-----------------+
| 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 | *               |
+--------+----------+-----------------+
     

Einige Anmerkungen: Bereiche, die kein Spiel haben, werden nicht in die Zählung erscheinen -   Sie werden nicht eine Null in der Zählspalte haben. Auch, ich bin mit dem   ROUND funktioniert hier. Sie können genauso einfach ersetzen Sie es mit TRUNCATE   wenn Sie das Gefühl es mehr Sinn macht für Sie.

Ich fand es hier http://blog.shlomoid.com /2011/08/how-to-quickly-create-histogram-in.html

Andere Tipps

Mike DelGaudio Antwort ist so, wie ich es tun, aber mit einer leichten Änderung:

select floor(mycol/10)*10 as bin_floor, count(*)
from mytable
group by 1
order by 1

Der Vorteil? Sie können die Behälter so groß oder so klein machen wie Sie wollen. Bins der Größe 100? floor(mycol/100)*100. Behälter von der Größe 5? floor(mycol/5)*5.

Bernardo.

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

Die Tabelle Bins enthält Spalten min_value und max_value, die die Behälter definieren. Beachten Sie, dass der Operator „join ... auf x zwischen y und z“ ist inklusive.

tabelle1 ist der Name der Datentabelle

Ofri Raviv Antwort ist ganz in der Nähe, aber nicht korrekt. Die count(*) wird 1 auch wenn es Null resultiert in einem Histogramm-Intervall. Die Abfrage Bedürfnisse modifiziert werden eine bedingte sum zu verwenden:

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

Solange es nicht zu viele Intervalle, das ist eine ziemlich gute Lösung.

habe ich ein Verfahren, das automatisch eine temporäre Tabelle für Behälter erzeugen nach einer bestimmten Anzahl oder Größe verwendet werden kann, für die spätere Verwendung mit Ofri Raviv-Lösung.

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

Dies wird die Histogrammzählwert nur für die Behälter erzeugen, die aufgefüllt werden. David West sollte Recht in seiner Korrektur sein, aber aus irgendeinem Grunde, unpopulated Bins erscheint nicht im Ergebnis für mich (trotz der Verwendung eines LEFT JOIN - Ich verstehe nicht, warum)

.

sollte, die funktionieren. Nicht so elegant, aber immer noch:

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

Mike 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 

Zusätzlich zu großer Antwort https://stackoverflow.com/a/10363145/916682 , können Sie phpMyAdmin Chart-Tool für ein schönes Ergebnis:

eingeben Bild Beschreibung hier

eingeben Bild Beschreibung hier

Equal Breite Binning in eine gegebene Anzahl der Bins:

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;

Beachten Sie, dass die 0.0000001 gibt es sicher zu stellen, dass die Datensätze mit dem Wert max (col) gleich nicht seine eigenen bin macht einfach von selbst. Auch die additive Konstante gibt es um sicherzustellen, dass die Abfrage nicht von Null auf Teilung nicht versagen, wenn alle Werte in der Spalte identisch sind.

Beachten Sie auch, dass die Anzahl der Behälter (10 im Beispiel) sollte mit einer Kommazeichen zu vermeiden Integer-Division (die unbereinigten bin_width kann dezimal) geschrieben werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top