سؤال

هل هناك طريقة لتحديد أحجام سلة في 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 | 
------------------------------

أعتقد أن هذا لا يمكن تحقيقه بطريقة مستقيمة إلى الأمام ولكن الإشارة إلى أي إجراء مخزن ذي صلة سيكون جيدًا أيضًا.

هل كانت مفيدة؟

المحلول

هذا منشور حول طريقة سريعة للغاية لإنشاء رسم بياني في MySQL للقيم الرقمية.

هناك طرق أخرى متعددة لإنشاء رسم بياني أفضل وأكثر مرونة ، باستخدام عبارات الحالة وأنواع أخرى من المنطق المعقد. تفوزني هذه الطريقة بمرور الوقت مرارًا وتكرارًا لأنه من السهل جدًا تعديله لكل حالة استخدام ، وقصيرة وموجزة للغاية. هذا هو كيف نفعل ذلك:

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

بعض الملاحظات: لن تظهر النطاقات التي لا تطابق في العدد - لن يكون لديك صفر في عمود العد. أيضا ، أنا أستخدم وظيفة الجولة هنا. يمكنك بسهولة استبداله باقتداد إذا شعرت أنه أكثر منطقية بالنسبة لك.

لقد وجدت هنا http://blog.shlomoid.com/2011/08/how-to-quickly-create-histogram-in.html

نصائح أخرى

إجابة Mike 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 هو اسم جدول البيانات

إجابة Ofri Raviv قريبة جدًا ولكنها غير صحيحة. ال 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

سيؤدي ذلك إلى توليد عدد الرسم البياني فقط للأصوات المأهولة بالسكان. يجب أن يكون David West على حق في تصحيحه ، لكن لسبب ما ، لا تظهر صناديق غير مسبقة في النتيجة بالنسبة لي (على الرغم من استخدام انضمام يسار - لا أفهم السبب).

التي يجب أن تعمل. ليس أنيقًا جدًا ولكن لا يزال:

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 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 غير المعدل).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top