2008-10-24 4 views
148

मान लीजिए मेरे पास एक संख्यात्मक कॉलम वाला एक टेबल है (इसे "स्कोर" कहें)।एसक्यूएल में, आप श्रेणियों में "समूह द्वारा" कैसे हो सकते हैं?

मैं गणना की एक तालिका उत्पन्न करना चाहता हूं, जो दिखाता है कि प्रत्येक श्रेणी में कितनी बार स्कोर दिखाई देते हैं।

उदाहरण के लिए:

 
score range | number of occurrences 
------------------------------------- 
    0-9  |  11 
    10-19  |  14 
    20-29  |   3 
    ...  |  ... 

इस उदाहरण में 19 के लिए 10 की रेंज में स्कोर के साथ 0 से 9 तक, 14 पंक्तियों की सीमा में स्कोर के साथ 11 पंक्तियाँ, और में स्कोर के साथ 3 पंक्तियों वहाँ थे सीमा 20-29।

क्या इसे स्थापित करने का कोई आसान तरीका है? आप क्या सलाह देते हैं?

उत्तर

114

न तो की यादृच्छित संख्या के साथ 100 पंक्तियों आबादी: एसक्यूएल सर्वर के लिए सबसे सरल बयान इस प्रकार है SQLServer 2000 पर उच्चतम मतदान वाले उत्तर सही हैं। शायद वे एक अलग संस्करण का उपयोग कर रहे थे।

यहाँ SQLServer पर उन दोनों का सही संस्करण हैं 2000.

select t.range as [score range], count(*) as [number of occurences] 
from (
    select case 
    when score between 0 and 9 then ' 0- 9' 
    when score between 10 and 19 then '10-19' 
    else '20-99' end as range 
    from scores) t 
group by t.range 

या

select t.range as [score range], count(*) as [number of occurences] 
from (
     select user_id, 
     case when score >= 0 and score< 10 then '0-9' 
     when score >= 10 and score< 20 then '10-19' 
     else '20-99' end as range 
    from scores) t 
group by t.range 
+0

क्या मैं एक और स्तंभ भी जोड़ सकता हूं (समूह गणना की तरह)। कहें कि मैं प्रत्येक स्कोर रेंज के लिए छात्रवृत्ति कॉलम को जोड़ता हूं। मैंने कोशिश की, लेकिन इसे सही नहीं मिला –

+0

अच्छा जवाब @ रॉन टफिन, हालांकि जब आपके पास 10-20, 100-200 की तरह दो श्रेणियां हैं, तो ऑर्डर काम नहीं करता है। आपके पास ऑर्डर के लिए 10-20, 100-200,20-30 आदि जैसे ऑर्डर होंगे? –

+2

@ZoHas यह एक हैक का थोड़ा सा है लेकिन यह काम करता है: लेन (टी। श्रेणी) द्वारा क्रमबद्ध, t.range –

5
create table scores (
    user_id int, 
    score int 
) 

select t.range as [score range], count(*) as [number of occurences] 
from (
     select user_id, 
     case when score >= 0 and score < 10 then '0-9' 
     case when score >= 10 and score < 20 then '10-19' 
     ... 
     else '90-99' as range 
    from scores) t 
group by t.range 
+0

धन्यवाद! मैंने कोशिश की और मूल विचार बहुत अच्छा काम करता है, हालांकि मुझे जिस वाक्यविन्यास का उपयोग करना था वह थोड़ा अलग है। केवल "केस" कीवर्ड की आवश्यकता होती है और फिर अंतिम स्थिति के बाद, "श्रेणी के रूप में" आपको कीवर्ड "अंत" की आवश्यकता होती है। इसके अलावा, बहुत अच्छा काम किया- धन्यवाद! – Hugh

5
select cast(score/10 as varchar) + '-' + cast(score/10+9 as varchar), 
     count(*) 
from scores 
group by score/10 
+0

मुझे यह पसंद है, लेकिन यदि आप इसे प्रदर्शित करने जा रहे हैं तो आपको क्वेरी के बाहर की सीमाएं ठीक करनी होंगी। – tvanfosson

+0

यदि आप अपना उत्तर ठीक करने का निर्णय लेते हैं तो आपको पहले पंक्ति पर अपना स्कोर/10 बदलने की आवश्यकता है (स्कोर/10) * 10 दोनों के लिए अन्यथा आपको 30-39 के बजाय 3 - 12 मिलते हैं। मेरे अनुसार परिणाम नीचे सही क्रम में परिणाम प्राप्त करने के लिए आप एक आदेश जोड़ सकते हैं। –

19

postgres में (जहां || स्ट्रिंग संयोजन ऑपरेटर है):

select (score/10)*10 || '-' || (score/10)*10+9 as scorerange, count(*) 
from scores 
group by score/10 
order by 1 

देता है:

scorerange | count 
------------+------- 
0-9  | 11 
10-19  | 14 
20-29  |  3 
30-39  |  2 
-1

शायद आप जा रहे इस तरह की चीजों रखने के बारे में पूछ रहे हैं ..

सह यूआरएस आप प्रश्नों के लिए एक पूर्ण टेबल स्कैन का आह्वान करेंगे और यदि तालिका को लम्बाई (समेकन) की आवश्यकता वाली तालिका है तो आप एक बेहतर प्रदर्शन समाधान चाहते हैं, आप एक माध्यमिक तालिका बना सकते हैं और on insert जैसे नियमों का उपयोग कर सकते हैं - आप इसे देख सकते हैं।

सभी आरडीबीएमएस इंजनों के नियम नहीं हैं, हालांकि!

1
declare @RangeWidth int 

set @RangeWidth = 10 

select 
    Floor(Score/@RangeWidth) as LowerBound, 
    Floor(Score/@RangeWidth)[email protected] as UpperBound, 
    Count(*) 
From 
    ScoreTable 
group by 
    Floor(Score/@RangeWidth) 
28

मुझे यहां जवाब दिखाई देता है जो SQL सर्वर के वाक्यविन्यास में काम नहीं करेगा। मैं का प्रयोग करेंगे:

select t.range as [score range], count(*) as [number of occurences] 
from (
    select case 
    when score between 0 and 9 then ' 0-9 ' 
    when score between 10 and 19 then '10-19' 
    when score between 20 and 29 then '20-29' 
    ... 
    else '90-99' end as range 
    from scores) t 
group by t.range 

संपादित करें: टिप्पणियाँ

+0

यह संभवतः SQL सर्वर का संस्करण है जिसका उपयोग मैं कर रहा हूं लेकिन काम करने के लिए अपना उदाहरण प्राप्त करने के लिए (मैं उन्हें वोट देने से पहले चीजों का परीक्षण करता हूं) मुझे प्रत्येक 'कब' के बाद 'केस' के बाद से 'स्कोर' ले जाना पड़ा। –

+3

आप सही हैं, और सुधार के लिए धन्यवाद। जाहिर है जब आप कीवर्ड 'केस' के बाद चर डालते हैं, तो आप केवल सटीक मिलान कर सकते हैं, अभिव्यक्ति नहीं। मैं उनसे पूछने के रूप में सवालों के जवाब देने से बहुत कुछ सीखता हूं। :-) –

9

देख जेम्स कुरान का जवाब मेरी राय में सबसे संक्षिप्त था, लेकिन उत्पादन सही नहीं था।

SELECT 
    [score range] = CAST((Score/10)*10 AS VARCHAR) + ' - ' + CAST((Score/10)*10+9 AS VARCHAR), 
    [number of occurrences] = COUNT(*) 
FROM #Scores 
GROUP BY Score/10 
ORDER BY Score/10 

यह एक #Scores अस्थायी तालिका मैं इसे परीक्षण के लिए किया हो जाती है, मैं सिर्फ 0 और 99

+1

आह ... वास्तव में तालिका बनाने के लिए समय निकालने का लाभ है। (मैंने एक छोटी सी पंक्तियों के साथ बहुत कम पंक्तियों के साथ एक मौजूदा तालिका का उपयोग किया) –

25

एक वैकल्पिक दृष्टिकोण एक तालिका में पर्वतमाला भंडारण, बजाय उन्हें में एम्बेड शामिल होगा क्वेरी।

LowerLimit UpperLimit Range 
0    9   '0-9' 
10   19   '10-19' 
20   29   '20-29' 
30   39   '30-39' 

और एक प्रश्न है कि इस तरह दिखता है:: आप एक मेज के साथ खत्म होता है, फोन यह रेंज, कि इस तरह दिखता है

Select 
    Range as [Score Range], 
    Count(*) as [Number of Occurences] 
from 
    Ranges r inner join Scores s on s.Score between r.LowerLimit and r.UpperLimit 
group by Range 

यह एक मेज की स्थापना का क्या मतलब है, लेकिन यह होगा वांछित श्रेणियां बदलते समय बनाए रखना आसान हो। कोई कोड आवश्यक परिवर्तन नहीं है!

+0

मैंने डेटाबेस प्रशासकों [वेरिएबल बाल्टी रेंज का उपयोग करके पैटर्न डेटा के लिए टेबल डिज़ाइन] पर एक प्रश्न पूछा (http://dba.stackexchange.com/questions/94275/table-design-for-patterned-data-using-variable -बकेट-रेंज) जिन्हें उत्तर नहीं मिला, लेकिन मैंने एक ऐसी प्रणाली तैयार की जिसे आपके द्वारा वर्णित श्रेणियां हैं। इस जवाब को प्यार करो। – OmegaMan

0
select t.blah as [score range], count(*) as [number of occurences] 
from (
    select case 
    when score between 0 and 9 then ' 0-9 ' 
    when score between 10 and 19 then '10-19' 
    when score between 20 and 29 then '20-29' 
    ... 
    else '90-99' end as blah 
    from scores) t 
group by t.blah 

सुनिश्चित करें कि आप 'सीमा' के अलावा किसी अन्य शब्द का उपयोग करता है, तो आप MySQL में हैं, या आप ऊपर के उदाहरण को चलाने के लिए एक त्रुटि प्राप्त होगी बनाओ।

1

क्योंकि कॉलम को क्रमबद्ध किया जा रहा है (Range) एक स्ट्रिंग है, संख्यात्मक सॉर्टिंग के बजाय स्ट्रिंग/शब्द सॉर्टिंग का उपयोग किया जाता है।

जब तक संख्या लंबाई बाहर छंटाई अभी भी शब्दार्थ सही होना चाहिए के रूप में तार पैड को शून्य है:

SELECT t.range AS ScoreRange, 
     COUNT(*) AS NumberOfOccurrences 
    FROM (SELECT CASE 
        WHEN score BETWEEN 0 AND 9 THEN '00-09' 
        WHEN score BETWEEN 10 AND 19 THEN '10-19' 
        ELSE '20-99' 
       END AS Range 
      FROM Scores) t 
GROUP BY t.Range 

रेंज मिलाया जाता है, तो बस पैड एक अतिरिक्त शून्य:

SELECT t.range AS ScoreRange, 
     COUNT(*) AS NumberOfOccurrences 
    FROM (SELECT CASE 
        WHEN score BETWEEN 0 AND 9 THEN '000-009' 
        WHEN score BETWEEN 10 AND 19 THEN '010-019' 
        WHEN score BETWEEN 20 AND 99 THEN '020-099' 
        ELSE '100-999' 
       END AS Range 
      FROM Scores) t 
GROUP BY t.Range 
3

मैं इसे थोड़ा अलग तरीके से करूँगा ताकि यह हर मामले को परिभाषित किए बिना स्केल करे:

select t.range as [score range], count(*) as [number of occurences] 
from (
    select FLOOR(score/10) as range 
    from scores) t 
group by t.range 

परीक्षण नहीं किया गया है, लेकिन आपको विचार मिलता है ...

2

यह आपको श्रेणियां निर्दिष्ट करने की अनुमति नहीं देगा, और SQL सर्वर अज्ञेयवादी होना चाहिए। गणित एफटीडब्ल्यू!

SELECT CONCAT(range,'-',range+9), COUNT(range) 
FROM (
    SELECT 
    score - (score % 10) as range 
    FROM scores 
) 
1

प्रयास करें

SELECT (str(range) + "-" + str(range + 9)) AS [Score range], COUNT(score) AS [number of occurances] 
FROM (SELECT score, int(score/10) * 10 AS range FROM scoredata) 
GROUP BY range; 
+3

यह सहायक होगा यदि आप इस बारे में कुछ स्पष्टीकरण जोड़ सकते हैं कि आपकी क्वेरी समस्या का समाधान कैसे करती है। –

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