एक SQL क्वेरी के साथ एकाधिक काउंट कैसे प्राप्त करें?


315

मैं सोच रहा हूं कि इस क्वेरी को कैसे लिखा जाए।

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

SELECT distributor_id, 
COUNT(*) AS TOTAL, 
COUNT(*) WHERE level = 'exec', 
COUNT(*) WHERE level = 'personal'

मुझे यह सब एक क्वेरी में वापस चाहिए।

इसके अलावा, यह एक पंक्ति में होना चाहिए, इसलिए निम्नलिखित काम नहीं करेगा:

'SELECT distributor_id, COUNT(*)
GROUP BY distributor_id'

1
क्या आप की यह क्वेरी ठीक से काम की है ?? SELECT distributor_id, COUNT(*) AS TOTAL, COUNT(*) WHERE level = 'exec', COUNT(*) WHERE level = 'personal'
प्रतीक

जवाबों:


689

आप CASEकुल फ़ंक्शन के साथ एक स्टेटमेंट का उपयोग कर सकते हैं । यह मूल रूप PIVOTसे कुछ RDBMS में एक समारोह के रूप में एक ही बात है :

SELECT distributor_id,
    count(*) AS total,
    sum(case when level = 'exec' then 1 else 0 end) AS ExecCount,
    sum(case when level = 'personal' then 1 else 0 end) AS PersonalCount
FROM yourtable
GROUP BY distributor_id

55
शानदार, यह अद्भुत है। बहुत बढ़िया जवाब। सिर्फ उन लोगों के लिए एक नोट जो यहां ठोकर खा चुके हैं। काउंट सभी पंक्तियों की गणना करेगा, योग एक केस स्टेटमेंट के साथ उपयोग किए जाने पर गणना के समान कार्य करेगा।
जॉन बॉलिंजर

1
शानदार समाधान! यह शायद ध्यान देने योग्य है कि यह विधि ठीक वैसे ही काम करती है यदि आप एक क्वेरी में बहुत सारी तालिकाओं को एक साथ जोड़ रहे हैं, क्योंकि उप-प्रश्नों का उपयोग करने से उस उदाहरण में काफी गड़बड़ हो सकती है।
डैरेन क्रैब

7
इस बहुत ही सुंदर समाधान के लिए धन्यवाद। Btw, यह TSQL के साथ भी काम करता है।
एनी लगैंग

6
यह सबसे अच्छा जवाब क्यों नहीं हो सकता है: हमेशा एक पूर्ण तालिका स्कैन। काउंट-सबक्वेरीज़, या नेस्टेड काउंट्स के चयन में शामिल होने पर विचार करें। हालाँकि, कोई अनुक्रमणिका मौजूद नहीं है, यह सबसे अच्छा हो सकता है क्योंकि आपने केवल एक टेबल स्कैन बनाम एकाधिक की गारंटी दी है। उत्तर देखें @KevinBalmforth
YoYo

1
@JohnBallinger, 'गणना सभी पंक्तियों की गणना होती है' - COUNTकी गणना होती है distributor_idबुद्धिमान। तालिका की सभी पंक्तियाँ, सही नहीं है?
इस्तियाक अहमद

87

एक तरीका जो निश्चित रूप से काम करता है

SELECT a.distributor_id,
    (SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
    (SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
    (SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM (SELECT DISTINCT distributor_id FROM myTable) a ;

संपादित करें:
देखें : केविन बाल्मफोर्थ के प्रदर्शन का ब्रेक डाउन क्यों आप संभवतः इस पद्धति का उपयोग नहीं करना चाहते हैं और इसके बजाय @ टैरिन के जवाब का चयन करना चाहिए। मैं इसे छोड़ रहा हूं ताकि लोग उनके विकल्पों को समझ सकें।


2
इससे मुझे यह पता लगाने में मदद मिली कि एकाधिक गणना कैसे की जाती है और प्रत्येक गणना में एक कॉलम होने के साथ उनका चयन करें। महान काम करता है - धन्यवाद!
मार्क

2
मैं यहां जो कुछ भी प्रदान करता हूं, उसका उपयोग करने में सक्षम था। अब सब कुछ एक ही प्रश्न में है, कई प्रश्नों के बजाय। पृष्ठ कई प्रश्नों के साथ 5-8 सेकंड की तुलना में एक सेकंड से भी कम समय में लोड होता है। इसे प्यार करना। धन्यवाद, नोटम।
वेन बैरन

1
यदि प्रत्येक उप क्वेरी वास्तव में किसी इंडेक्स को हिट करती है तो यह अच्छी तरह से काम कर सकती है। यदि नहीं, तो sum(case...)समाधान पर विचार किया जाना चाहिए।
योयो

1
ध्यान दें कि विशिष्ट के विकल्प के रूप में, जैसा कि मैंने सुधार किया है, आप @Mihai शो के group byसाथ एक सरल के साथ एक संपूर्ण नेस्टेड क्वेरी को बदलने के लाभ के साथ / बेहतर उपयोग भी कर सकते हैं count(*)- आगे MySQL केवल सिंटैक्स सरलीकरण के साथ।
योयो

43
SELECT 
    distributor_id, 
    COUNT(*) AS TOTAL, 
    COUNT(IF(level='exec',1,null)),
    COUNT(IF(level='personal',1,null))
FROM sometable;

COUNTकेवल non nullमान गिनाता है और आपकी स्थिति संतुष्ट होने पर ही DECODEगैर शून्य मान लौटाएगा 1


distributor_idक्वेरी कौन सा दिखाएगा? यह कुल मिलाकर 1 पंक्ति दिखाता है।
इस्तियाक अहमद

ओपी के पास कॉलम पर एक समूह है जिसे मेरे उत्तर में छोड़ दिया गया था।
माजिद लाईसी

आपने मेरी जान बचाई, अन्य सभी aswers MySQL में कई पंक्तियों को वापस करते हैं। बहुत बहुत धन्यवाद
Abner

1
@ अब्नेर को खुशी है कि यह अभी भी 8 साल बाद मदद करता है :)
माजिद लस्सी

@MajidLaissi हाँ, यह एक मिनट से भी कम समय के लिए मेरी क्वेरी समय बदल गया। :)
एबनर

25

अन्य पोस्ट किए गए उत्तरों पर बिल्डिंग।

ये दोनों सही मान उत्पन्न करेंगे:

select distributor_id,
    count(*) total,
    sum(case when level = 'exec' then 1 else 0 end) ExecCount,
    sum(case when level = 'personal' then 1 else 0 end) PersonalCount
from yourtable
group by distributor_id

SELECT a.distributor_id,
          (SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
          (SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
          (SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
       FROM myTable a ; 

हालांकि, प्रदर्शन काफी भिन्न है, जो स्पष्ट रूप से अधिक प्रासंगिक होगा क्योंकि डेटा की मात्रा बढ़ती है।

मैंने पाया कि, कोई भी इंडेक्स टेबल पर परिभाषित नहीं किया गया था, SUM का उपयोग करने वाली क्वेरी एक सिंगल टेबल स्कैन करेगी, जबकि COUNT के साथ क्वेरी कई टेबल स्कैन करेगी।

एक उदाहरण के रूप में, निम्न स्क्रिप्ट चलाएँ:

IF OBJECT_ID (N't1', N'U') IS NOT NULL 
drop table t1

create table t1 (f1 int)


    insert into t1 values (1) 
    insert into t1 values (1) 
    insert into t1 values (2)
    insert into t1 values (2)
    insert into t1 values (2)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (3)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)
    insert into t1 values (4)


SELECT SUM(CASE WHEN f1 = 1 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 2 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 3 THEN 1 else 0 end),
SUM(CASE WHEN f1 = 4 THEN 1 else 0 end)
from t1

SELECT 
(select COUNT(*) from t1 where f1 = 1),
(select COUNT(*) from t1 where f1 = 2),
(select COUNT(*) from t1 where f1 = 3),
(select COUNT(*) from t1 where f1 = 4)

2 चयनित बयानों को हाइलाइट करें और प्रदर्शन अनुमानित निष्पादन योजना आइकन पर क्लिक करें। आप देखेंगे कि पहला स्टेटमेंट एक टेबल स्कैन करेगा और दूसरा 4 करेगा। जाहिर है एक टेबल स्कैन 4 से बेहतर है।

एक संकुल सूचकांक जोड़ना भी दिलचस्प है। उदाहरण के लिए

Create clustered index t1f1 on t1(f1);
Update Statistics t1;

ऊपर का पहला चयन एक एकल संकुल सूचकांक स्कैन करेगा। दूसरा Select 4 Clustered Index Seeks करेगा, लेकिन वे अभी भी एक Clustered Index Scan की तुलना में अधिक महंगे हैं। मैंने 8 मिलियन पंक्तियों वाली तालिका पर एक ही चीज़ की कोशिश की और दूसरा चयन अभी भी बहुत अधिक महंगा था।


23

MySQL के लिए, इसे छोटा किया जा सकता है:

SELECT distributor_id,
    COUNT(*) total,
    SUM(level = 'exec') ExecCount,
    SUM(level = 'personal') PersonalCount
FROM yourtable
GROUP BY distributor_id

1
इस क्वेरी में वास्तव में आवश्यक "
वितरक_आईडी

2
@ user1451111 मूल सवाल यह है तो यह जवाब है सवाल पर ही निर्भर करता है
अल- Mothafar

11

ठीक है, अगर आपके पास यह सब एक क्वेरी में होना चाहिए, तो आप एक संघ कर सकते हैं:

SELECT distributor_id, COUNT() FROM ... UNION
SELECT COUNT() AS EXEC_COUNT FROM ... WHERE level = 'exec' UNION
SELECT COUNT(*) AS PERSONAL_COUNT FROM ... WHERE level = 'personal';

या, यदि आप प्रसंस्करण के बाद कर सकते हैं:

SELECT distributor_id, COUNT(*) FROM ... GROUP BY level;

आप प्रत्येक स्तर के लिए गिनती प्राप्त करेंगे और कुल प्राप्त करने के लिए उन सभी को योग करने की आवश्यकता होगी।


फ़ंक्शन के UNIONकई उदाहरणों वाली रिपोर्ट जनरेट करते समय बहुत मददगार पाया गया COUNT(*)
जेम्स ओ।

परिणाम दिखाता है #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') FROM distributors UNION SELECT COUNT() AS EXEC_COUNT FROM distributors WHERE ' at line 1
इस्तियाक अहमद

सभी प्रश्नों से लौटे स्तंभों की संख्या, जिस पर एक UNION लागू है, समान होना चाहिए। @IstiaqueAhmed शायद यही कारण है कि आपकी त्रुटि के पीछे।
user1451111

भविष्य में इस जवाब पर ठोकर खाने वाले किसी भी व्यक्ति के लिए एक नोट। यहाँ वर्णित 'आफ्टर प्रोसेसिंग' तकनीक तब समस्या का कारण बन सकती है जब 'स्तर' कॉलम के कुछ मान NULL हों। उस स्थिति में सभी उप-गणनाओं का योग कुल पंक्ति गणना के बराबर नहीं होगा।
user1451111

6

मैं ऐसा कुछ करता हूं जहां मैं कॉलम ए में इसे पहचानने के लिए प्रत्येक तालिका को एक स्ट्रिंग नाम देता हूं, और कॉलम के लिए एक गिनती। फिर मैंने उन सभी को संघ किया ताकि वे ढेर हो जाएं। मेरी राय में परिणाम बहुत अच्छा है - यह सुनिश्चित नहीं है कि यह अन्य विकल्पों की तुलना में कितना कुशल है, लेकिन मुझे वह मिला जो मुझे चाहिए था।

select 'table1', count (*) from table1
union select 'table2', count (*) from table2
union select 'table3', count (*) from table3
union select 'table4', count (*) from table4
union select 'table5', count (*) from table5
union select 'table6', count (*) from table6
union select 'table7', count (*) from table7;

परिणाम:

-------------------
| String  | Count |
-------------------
| table1  | 123   |
| table2  | 234   |
| table3  | 345   |
| table4  | 456   |
| table5  | 567   |
-------------------

1
a query that I created makes ...- वह प्रश्न कहाँ है?
इस्तियाक अहमद

2
कैसे जोड़ने के लिए जहां सभी तालिकाओं के लिए प्रयोग किया जाता है

3

ब्लूफेट के आधार पर एक अतिरिक्त बारीकियों के साथ स्वीकृत प्रतिक्रिया के आधार पर OVER():

SELECT distributor_id,
    COUNT(*) total,
    SUM(case when level = 'exec' then 1 else 0 end) OVER() ExecCount,
    SUM(case when level = 'personal' then 1 else 0 end) OVER () PersonalCount
FROM yourtable
GROUP BY distributor_id

OVER()() में कुछ नहीं के साथ उपयोग करने से आपको संपूर्ण डेटासेट की कुल गिनती मिलेगी।


1

मुझे लगता है कि यह आपके लिए भी काम कर सकता है select count(*) as anc,(select count(*) from Patient where sex='F')as patientF,(select count(*) from Patient where sex='M') as patientM from anc

और भी आप इस तरह से संबंधित तालिकाओं का चयन और गणना कर सकते हैं select count(*) as anc,(select count(*) from Patient where Patient.Id=anc.PatientId)as patientF,(select count(*) from Patient where sex='M') as patientM from anc

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