SQL स्टेटमेंट के साथ प्रतिशत की गणना कैसे करें


177

मेरे पास एक SQL सर्वर तालिका है जिसमें उपयोगकर्ता और उनके ग्रेड हैं। सादगी के लिए, केवल 2 कॉलम हैं - nameऔर कहते हैं grade। तो एक विशिष्ट पंक्ति का नाम होगा: "जॉन डो", ग्रेड: "ए"।

मैं एक एसक्यूएल स्टेटमेंट की तलाश कर रहा हूं, जिसमें सभी संभावित उत्तरों का प्रतिशत मिलेगा। (ए, बी, सी, आदि ...) इसके अलावा, क्या ऐसा करने के लिए सभी संभव उत्तरों को परिभाषित किए बिना ऐसा करने का एक तरीका है (पाठ क्षेत्र खोलें - उपयोगकर्ता 'पास / असफल', 'कोई नहीं' आदि दर्ज कर सकते हैं ...)

अंतिम उत्पादन मैं देख रहा हूँ A: 5%, B: 15%, C: 40%, आदि ...

जवाबों:


227

मैंने निम्नलिखित परीक्षण किया है और यह काम करता है। Gordyii द्वारा उत्तर करीब था, लेकिन गलत स्थान पर 100 का गुणन था और कुछ लापता कोष्ठक थे।

Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade

21
यह पूर्णांक में परिणाम देता है। परिणामों की संख्या 100 के बराबर नहीं है।
थंडर

10
तालिका में दो बार स्कैन किए जाने के रूप में सबसे कुशल नहीं है। इसके अलावा अगर एक से अधिक टेबल संदर्भित है तो क्वेरी इतनी सरल नहीं लगेगी।
एलेक्स आजा

14
@ यदि आप दशमलव मानों के लिए 100 से 100.0 बदल सकते हैं।
जोसेफ

क्या कोई समझा सकता है कि SQL क्वेरी का गणितीय सिंटैक्स वह क्यों नहीं है जो आप सामान्य रूप से करने की अपेक्षा करते हैं? उदाहरण के लिए सामान्य मैं कुल मिलाकर 100 से गुणा किया होगा? तार्किक दृष्टि से इस बारे में जिज्ञासु उत्सुक हैं।
डिजिटालसा 1

4
@ Digitalsa1nt (१०० * २) / ४ = ५०, (२/४) * १०० = ५० जब तक प्रगणक है तब तक गुणा किया जाता है। SQL कथनों की पूर्वता के कारण यह समान होगा। हालाँकि, डेटा प्रकारों के कारण यदि आप 100 का उपयोग कर रहे हैं, तब भी आप परिणाम को 0 दशमलव तक प्राप्त कर सकते हैं, जिसे आप% के लिए चाहते हैं, जैसे कि यदि आप इसे विभाजन ऑपरेशन के बाद डालते हैं, तो आपको यह सुनिश्चित करना होगा कि आप एक डेटा प्रकार जो आप संभाल सकते हैं, को डाल दें दशमलव स्थान अन्यथा आप 100 या 0 के साथ समाप्त हो जाएंगे और कभी भी वास्तविक प्रतिशत नहीं होगा
मैट

231
  1. सबसे कुशल (ओवर का उपयोग करके)।

    select Grade, count(*) * 100.0 / sum(count(*)) over()
    from MyTable
    group by Grade
    
  2. यूनिवर्सल (कोई SQL संस्करण)।

    select Grade, count(*) * 100.0 / (select count(*) from MyTable)
    from MyTable
    group by Grade;
    
  3. CTE के साथ, सबसे कम कुशल।

    with t(Grade, GradeCount) 
    as 
    ( 
        select Grade, count(*) 
        from MyTable
        group by Grade
    )
    select Grade, GradeCount * 100.0/(select sum(GradeCount) from t)
    from t;
    

13
ओवर () मेरे SQL सर्वर 2008 पर पूरी तरह से काम किया, मैंने पुष्टि करने के लिए गणित किया। इसे 2 दशमलव स्थानों पर राउंड करने के लिए मैंने CAST (गणना ( ) * 100.0 / योग (काउंट ) ( ) से अधिक () AS DECIMAL (18, 2)) का उपयोग किया। पोस्ट के लिए धन्यवाद!
आरजेबी

3
यदि आप 100 गुणा (उदाहरण के अंकगणितीय अतिप्रवाह त्रुटि को डेटा प्रकार int में परिवर्तित करने में त्रुटि) पर अतिप्रवाह करते हैं , तो इसे हर में विभाजन के साथ बदलें:cast((count(*) / (sum(count(*)) over() / 100)) AS DECIMAL(18, 2)) as Percentage
निकिता जी।

@RJB जब आप आउटपुट को दशमलव के रूप में कास्टिंग कर रहे हों तो आपको 100.0 से गुणा नहीं करना चाहिए?
23:91 पर AS91

2
@ AS91, क्योंकि कास्ट टू दशमलव होता है विभाजन ऑपरेशन के बाद। यदि आप एक इंट (100) छोड़ते हैं, तो दूसरे इंट से विभाजित होने के परिणामस्वरूप एक इंट भी होगा, जो परिणाम को गोल करेगा। यही कारण है कि चाल हमेशा वास्तविक विभाजन से पहले लाभांश पर एक कलाकार को बाध्य करने के लिए होती है (आप या तो 1.0 या शाब्दिक रूप से शाब्दिक दशमलव से गुणा कर सकते हैं)
luiggig

विकल्प 1 over()पोस्टग्रैस्कल 10 पर महान काम करता है
जेम्स डेली

40

कुल प्राप्त करने के लिए एक अलग सीटीई का उपयोग करने के बजाय, आप "विभाजन द्वारा" खंड के बिना एक विंडो फ़ंक्शन का उपयोग कर सकते हैं।

यदि आप उपयोग कर रहे हैं:

count(*)

एक समूह के लिए गिनती प्राप्त करने के लिए, आप इसका उपयोग कर सकते हैं:

sum(count(*)) over ()

कुल गिनती प्राप्त करने के लिए।

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

select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;

यह मेरे अनुभव में तेज है, लेकिन मुझे लगता है कि यह आंतरिक रूप से कुछ मामलों में एक अस्थायी तालिका का उपयोग कर सकता है (जब मैंने "सेट आँकड़ों पर चल रहा है" तो "वर्कटेबल" देखा है)।

संपादित करें: मुझे यकीन नहीं है कि यदि मेरा उदाहरण क्वेरी वह है जिसे आप ढूंढ रहे हैं, तो मैं सिर्फ यह दिखा रहा था कि विंडोिंग फ़ंक्शन कैसे काम करता है।


+1। यह भी खूब रही। इसका उपयोग तब भी किया जा सकता है जब 'तालिका' के स्थान पर एक चयन कथन हो।
mr_georg

1
यह एक स्पूल का उपयोग करता है tempdbजिसमें कार्य तालिका है। तार्किक रीड अधिक लगते हैं लेकिन उन्हें सामान्य से भिन्न गिना जाता है
मार्टिन स्मिथ

1
वास्तव में, COUNT(*) OVER ()आपकी क्वेरी में पूरी तरह से असंबंधित आंकड़ा लौटेगा (विशेष रूप से, समूहित परिणाम सेट की पंक्तियों की संख्या )। आपको SUM(COUNT(*)) OVER ()इसके बजाय उपयोग करना चाहिए ।
एंड्री एम

10

आपको कुल ग्रेड की गणना करनी है यदि यह SQL 2005 है तो आप सीटीई का उपयोग कर सकते हैं

    WITH Tot(Total) (
    SELECT COUNT(*) FROM table
    )
    SELECT Grade, COUNT(*) / Total * 100
--, CONVERT(VARCHAR, COUNT(*) / Total * 100) + '%'  -- With percentage sign
--, CONVERT(VARCHAR, ROUND(COUNT(*) / Total * 100, -2)) + '%'  -- With Round
    FROM table
    GROUP BY Grade

1
बेशक, यह केवल तालिका में मौजूद ग्रेड कोड के लिए प्रतिशत देता है, न कि उन लोगों के लिए जो मौजूद हो सकते हैं और नहीं। लेकिन प्रासंगिक (मान्य) ग्रेड कोड की एक निश्चित सूची के बिना, आप बेहतर नहीं कर सकते। इसलिए मुझ से +1।
जोनाथन लेफ़लर

1
मेरे लिए छिपे हुए मणि को आप CONVERT से टिप्पणी कर रहे थे।
क्रिस कैटिगनी

9

आपको ग्रेड फ़ील्ड पर समूह बनाने की आवश्यकता है। यह क्वेरी आपको देनी चाहिए जो आपके लिए किसी भी डेटाबेस में ढूंढ रहा है।

    Select Grade, CountofGrade / sum(CountofGrade) *100 
    from
    (
    Select Grade, Count(*) as CountofGrade
    From Grades
    Group By Grade) as sub
    Group by Grade

आपको उस सिस्टम को निर्दिष्ट करना चाहिए जिसका आप उपयोग कर रहे हैं।


2
चूँकि आपके पास बाहरी चयन में एक समुच्चय ('योग (काउंटऑफग्रेड)') है, क्या आपको इसमें क्लॉज द्वारा भी समूह की आवश्यकता नहीं है? और मानक एसक्यूएल में, मुझे लगता है कि आप कुल प्राप्त करने के लिए '/ (सेक्ट (*) फ़ॉर ग्रैडेस)' का चयन कर सकते हैं।
जोनाथन लेफ़लर

IBM Informix डायनेमिक सर्वर, चयन-सूची में नग्न SUM को पसंद नहीं करता है (हालाँकि यह शिकायत होने पर कुछ हद तक मददगार संदेश देता है)। जैसा कि मेरे उत्तर और पूर्व टिप्पणी में उल्लेख किया गया है, चयन-सूची में एक पूर्ण उप-चयन अभिव्यक्ति का उपयोग आईडीएस में काम करता है।
जोनाथन लेफ़लर

यह भी बेहतर है क्योंकि कोई जटिल लागू कर सकता है जहां आंतरिक क्वेरी।
mvmn 12

9

मैं बस एक प्रतिशत बाहर काम करने की जरूरत है जब मैं इसका इस्तेमाल करते हैं ..

ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage

ध्यान दें कि 100.0 रिटर्न दशमलव में आता है, जबकि 100 पर यह अपने आप को निकटतम पूरे नंबर पर परिणाम देगा, यहां तक ​​कि ROUND () फ़ंक्शन के साथ!


7

निम्नलिखित काम करना चाहिए

ID - Key
Grade - A,B,C,D...

संपादित करें: स्थानांतरित किया * 100और 1.0यह सुनिश्चित करने के लिए जोड़ा कि यह पूर्णांक विभाजन नहीं करता है

Select 
   Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade

1
यह काम करता है, लेकिन सभी उत्तर 0 के रूप में वापस आते हैं - क्या मुझे उचित उत्तर देखने के लिए किसी प्रकार की संख्या स्वरूपण या रूपांतरण करने की आवश्यकता है?
एलेक्स

1
ग्रेड का चयन करें, राउंड (काउंट) (ग्रेड) * 100.0 / ((सेलेक्ट (ग्रेड) ग्रेड से) का चयन करें) * 1.0), 2) ग्रेड ग्रुप से ग्रेड तक एसक्यूएल-सर्वर रेटुरेंड में एक राउंड फंक्शन जोड़ने के लिए जैसे: 21.56000000000
थंडर

5

यह, मेरा मानना ​​है, एक सामान्य समाधान है, हालांकि मैंने आईबीएम इंफॉर्मिक्स डायनेमिक सर्वर 11.50.FC3 का उपयोग करके इसका परीक्षण किया। निम्नलिखित प्रश्न:

SELECT grade,
       ROUND(100.0 * grade_sum / (SELECT COUNT(*) FROM grades), 2) AS pct_of_grades
    FROM (SELECT grade, COUNT(*) AS grade_sum
            FROM grades
            GROUP BY grade
         )
    ORDER BY grade;

क्षैतिज नियम के नीचे दिखाए गए परीक्षण डेटा पर निम्न आउटपुट देता है। ROUNDसमारोह डीबीएमएस विशिष्ट हो सकता है, लेकिन बाकी (शायद) नहीं है। (ध्यान दें कि गैर-पूर्णांक - DECIMAL, NUMERIC - अंकगणित का उपयोग करके गणना करने के लिए यह सुनिश्चित करने के लिए मैं 100 से 100.0 में बदल गया; टिप्पणियों को देखें और थंडर को धन्यवाद दें।)

grade  pct_of_grades
CHAR(1) DECIMAL(32,2)
A       32.26
B       16.13
C       12.90
D       12.90
E       9.68
F       16.13

CREATE TABLE grades
(
    id VARCHAR(10) NOT NULL,
    grade CHAR(1) NOT NULL CHECK (grade MATCHES '[ABCDEF]')
);

INSERT INTO grades VALUES('1001', 'A');
INSERT INTO grades VALUES('1002', 'B');
INSERT INTO grades VALUES('1003', 'F');
INSERT INTO grades VALUES('1004', 'C');
INSERT INTO grades VALUES('1005', 'D');
INSERT INTO grades VALUES('1006', 'A');
INSERT INTO grades VALUES('1007', 'F');
INSERT INTO grades VALUES('1008', 'C');
INSERT INTO grades VALUES('1009', 'A');
INSERT INTO grades VALUES('1010', 'E');
INSERT INTO grades VALUES('1001', 'A');
INSERT INTO grades VALUES('1012', 'F');
INSERT INTO grades VALUES('1013', 'D');
INSERT INTO grades VALUES('1014', 'B');
INSERT INTO grades VALUES('1015', 'E');
INSERT INTO grades VALUES('1016', 'A');
INSERT INTO grades VALUES('1017', 'F');
INSERT INTO grades VALUES('1018', 'B');
INSERT INTO grades VALUES('1019', 'C');
INSERT INTO grades VALUES('1020', 'A');
INSERT INTO grades VALUES('1021', 'A');
INSERT INTO grades VALUES('1022', 'E');
INSERT INTO grades VALUES('1023', 'D');
INSERT INTO grades VALUES('1024', 'B');
INSERT INTO grades VALUES('1025', 'A');
INSERT INTO grades VALUES('1026', 'A');
INSERT INTO grades VALUES('1027', 'D');
INSERT INTO grades VALUES('1028', 'B');
INSERT INTO grades VALUES('1029', 'A');
INSERT INTO grades VALUES('1030', 'C');
INSERT INTO grades VALUES('1031', 'F');

sql-server में पूर्णांक प्रतिशत देता है
थंडर

@ थंडर: दिलचस्प; क्या होता है यदि आप बदलते हैं, कहते हैं, 100 से 100.00?
जोनाथन लेफ्लर

यकीन है कि परिणाम 100.0
थंडर

4
SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
      FROM myTable
      GROUP BY Grade) Grades

3

किसी भी sql सर्वर संस्करण में आप इस तरह के सभी ग्रेड के कुल के लिए एक चर का उपयोग कर सकते हैं:

declare @countOfAll decimal(18, 4)
select @countOfAll = COUNT(*) from Grades

select
Grade,  COUNT(*) / @countOfAll * 100
from Grades
group by Grade

3

आप अपने से क्वेरी में एक सबसिलेक्ट का उपयोग कर सकते हैं (बिना पढ़े और सुनिश्चित करें कि जो तेज़ है):

SELECT Grade, COUNT(*) / TotalRows
FROM (SELECT Grade, COUNT(*) As TotalRows
      FROM myTable) Grades
GROUP BY Grade, TotalRows

या

SELECT Grade, SUM(PartialCount)
FROM (SELECT Grade, 1/COUNT(*) AS PartialCount
      FROM myTable) Grades
GROUP BY Grade

या

SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
      FROM myTable
      GROUP BY Grade) Grades

आप एक संग्रहीत प्रक्रिया (फ़ायरबर्ड सिंटैक्स के लिए माफी) का उपयोग कर सकते हैं:

SELECT COUNT(*)
FROM myTable
INTO :TotalCount;

FOR SELECT Grade, COUNT(*)
FROM myTable
GROUP BY Grade
INTO :Grade, :GradeCount
DO
BEGIN
    Percent = :GradeCount / :TotalCount;
    SUSPEND;
END

0

मेरा भी इसी तरह का मुद्दा था। आपको 100 के बजाय 1.0 से गुणा करके सही परिणाम प्राप्त करने में सक्षम होना चाहिए। उदाहरण के लिए छवि संलग्न है

ग्रेड का चयन करें, (काउंट (ग्रेड) * 1.0 /) (माईटेबल से काउंट (*) का चयन करें) माईटेबल ग्रुप से ग्रेड के रूप में स्कोर करें। संलग्न संदर्भ छवि देखें


कृपया चित्रों को जानकारी के रूप में साझा न करें जब तक कि बिल्कुल आवश्यक न हो। देखें: meta.stackoverflow.com/questions/303812/...
एएमसी

0

यह एक MS SQL में अच्छी तरह से काम कर रहा है। यह चरचर को दो-दशमलव-स्थानों-सीमित फ्लोट के परिणाम में बदल देता है।

Select field1, cast(Try_convert(float,(Count(field2)* 100) / 
Try_convert(float, (Select Count(*) From table1))) as decimal(10,2)) as new_field_name 
From table1 
Group By field1, field2;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.