2012-03-13 9 views
8

को देखते हुए करने के लिए:एसक्यूएल आवृत्ति वितरण क्वेरी समूह-से साथ पर्वतमाला गिनती और शामिल 0 मायने रखता है

table 'thing': 

age 
--- 
3.4 
3.4 
10.1 
40 
45 
49 

मैं हर 10 साल श्रृंखला के लिए चीजों की संख्या की गणना करना चाहते हैं, जैसे,

age_range | count 
----------+------- 
     0 |  2 
     10|  1 
     20|  0 
     30|  0 
     40|  3 

इस क्वेरी करीब आता है:

SELECT FLOOR(age/10) as age_range, COUNT(*) 
FROM thing 
GROUP BY FLOOR(age/10) ORDER BY FLOOR(age/10); 

आउटपुट:

age_range | count 
-----------+------- 
     0 |  1 
     1 |  2 
     4 |  3 

हालांकि, यह मुझे उन श्रेणियों को नहीं दिखाता है जिनमें 0 अंक हैं। मैं क्वेरी को कैसे संशोधित कर सकता हूं ताकि यह 0 गणनाओं के बीच की श्रेणियों को भी दिखा सके?

मुझे गिनती श्रेणियों के लिए समान स्टैक ओवरफ्लो प्रश्न मिले, कुछ 0 गणनाओं के लिए, लेकिन उनमें प्रत्येक श्रेणी निर्दिष्ट करने (या तो क्वेरी में श्रेणियों को हार्ड-कोडिंग करना, या किसी तालिका में श्रेणियां डालना) शामिल होना शामिल है। मैं ऊपर की तरह एक सामान्य क्वेरी का उपयोग करना पसंद करूंगा जहां मुझे प्रत्येक सीमा को स्पष्ट रूप से निर्दिष्ट करने की आवश्यकता नहीं है (उदा।, 0-10, 10-20, 20-30, ...)। मैं PostgreSQL 9.1.3 का उपयोग कर रहा हूँ।

क्या 0 गणनाओं को शामिल करने के लिए ऊपर दी गई सरल क्वेरी को संशोधित करने का कोई तरीका है?

समान:
Oracle: how to "group by" over a range?
Get frequency distribution of a decimal range in MySQL

उत्तर

10

बचाव के लिए generate_series:

select 10 * s.d, count(t.age) 
from generate_series(0, 10) s(d) 
left outer join thing t on s.d = floor(t.age/10) 
group by s.d 
order by s.d 

generate_series के लिए ऊपरी सीमा इसके बारे में पता एक अलग क्वेरी के साथ तुच्छ होना चाहिए, मैं सिर्फ एक प्लेसहोल्डर के रूप में 10 का इस्तेमाल किया ।

यह:

generate_series(0, 10) s(d) 

अनिवार्य रूप से एक एकल स्तंभ d जो 0 से 10 (सम्मिलित) के लिए मान के साथ s कहा जाता है एक इनलाइन तालिका उत्पन्न करता है।

यदि आवश्यक हो तो आप दो प्रश्नों को लपेट सकते हैं (एक सीमा को समझने के लिए, एक गणना की गणना करने के लिए)।

+0

यह अच्छा है नहीं था अगर। जानना अच्छा काम है। – Glenn

+0

सुरुचिपूर्ण उत्तर, @mu_is_too_short! मैंने इसे आजमाया और यह काम आया। मुझे इसकी ही खोज थी। धन्यवाद! –

+0

@Glenn: हाँ, 'gener_series' पागल-उपयोगी है, यह टाइमस्टैम्प के साथ भी अलविदा अलविदा कैलेंडर टेबल के साथ काम कर सकता है। –

1

आपको आयु सीमाओं की तालिका का आविष्कार करने के लिए कुछ तरीका चाहिए। पंक्ति संख्या आमतौर पर अच्छी तरह से काम करता है। बहुत सारी संख्याएं प्राप्त करने के लिए एक बड़ी मेज के खिलाफ एक कार्टशियन उत्पाद करें।

WITH RANGES AS (
SELECT (rownum - 1) * 10 AS age_range 
    FROM (SELECT row_number() OVER() as rownum 
      FROM pg_tables 
     ) n 
     ,(SELECT ceil(max(age)/10) range_end 
      FROM thing 
     ) m 
    WHERE n. rownum <= range_end 
) 
SELECT r.age_range, COUNT(t.age) AS count 
    FROM ranges r 
    LEFT JOIN thing t ON r.age_range = FLOOR(t.age/10) * 10 
    GROUP BY r.age_range 
    ORDER BY r.age_range; 

संपादित करें: म्यू बहुत छोटा है एक और अधिक सुरुचिपूर्ण जवाब है, लेकिन आप db पर एक generate_series समारोह, ... :)

संबंधित मुद्दे