SQL में, आप श्रेणियों में "समूह द्वारा" कैसे कर सकते हैं?


181

मान लीजिए कि मेरे पास एक संख्यात्मक कॉलम वाली तालिका है (इसे "स्कोर" कहते हैं)।

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

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

स्कोर रेंज | घटनाओं की संख्या
-------------------------------------
   0-9 | 1 1
  10-19 | 14
  20-29 | 3
   ... | ...

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

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

जवाबों:


143

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

क्या मैं किसी अन्य कॉलम (जैसे समूह गणना) को एकत्र कर सकता हूं। मैं प्रत्येक स्कोर रेंज के लिए छात्रवृत्ति कॉलम को एकीकृत करना चाहता हूं। मैंने कोशिश की, लेकिन सही नहीं हो रहा
मुनीश गोयल

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

2
@ZoHas यह एक हैक का एक सा है, लेकिन यह काम करता है: len (t.range) द्वारा आदेश, t.range
Ron Tuffin

पर बेहतर जवाब stackoverflow.com/questions/14730380/...
थंडर

1
यदि आपके पास अभी भी वाक्यविन्यास मुद्दे हैं, तो इस उत्तर को जांचें: dba.stackexchange.com/questions/22491/…
रॉबर्ट

33

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

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

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


मैंने वैरिएबल बकेट रेंज का उपयोग करते हुए पैटर्न प्रशासित डेटा के लिए डेटाबेस एडमिनिस्ट्रेटर टेबल डिज़ाइन पर एक प्रश्न पूछा , जिसका उत्तर नहीं मिला, लेकिन मैंने एक प्रणाली को डिज़ाइन किया है जिसमें आपके द्वारा बताई गई श्रेणियाँ हैं। इस उत्तर को प्यार करो।
27मेगामैन

31

मुझे यहां ऐसे उत्तर दिखाई देते हैं जो 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

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


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

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

23

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

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

11

जेम्स कुरेन का जवाब मेरी राय में सबसे संक्षिप्त था, लेकिन आउटपुट सही नहीं था। SQL सर्वर के लिए सबसे सरल कथन इस प्रकार है:

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

यह मानती है कि एक # अस्थायी तालिका जो मैंने इसका परीक्षण किया था, मैंने 0 और 99 के बीच यादृच्छिक संख्या के साथ 100 पंक्तियों को आबाद किया।


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

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

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

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

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

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

5

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

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

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
declare @RangeWidth int

set @RangeWidth = 10

select
   Floor(Score/@RangeWidth) as LowerBound,
   Floor(Score/@RangeWidth)+@RangeWidth as UpperBound,
   Count(*)
From
   ScoreTable
group by
   Floor(Score/@RangeWidth)

1
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

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
यह उपयोगी होगा यदि आप इस बारे में कुछ स्पष्टीकरण जोड़ सकते हैं कि आपकी क्वेरी समस्या का समाधान कैसे करती है।
डेवलिन ने

-1

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

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

हालांकि सभी RDBMS इंजन के नियम नहीं हैं!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.