SQL: यदि रिकॉर्ड मौजूद है तो ठीक से जाँच कैसे करें


207

कुछ SQL ट्यूनिंग-संबंधित प्रलेखन पढ़ते हुए, मैंने पाया:

SELECT COUNT(*) :

  • पंक्तियों की संख्या गिनता है।
  • अक्सर रिकॉर्ड के अस्तित्व को सत्यापित करने के लिए अनुचित रूप से उपयोग किया जाता है।

क्या SELECT COUNT(*)वाकई इतना बुरा है?

किसी रिकॉर्ड के अस्तित्व को सत्यापित करने का उचित तरीका क्या है?

जवाबों:


252

निम्नलिखित में से किसी एक का उपयोग करना बेहतर है:

-- Method 1.
SELECT 1
FROM table_name
WHERE unique_key = value;

-- Method 2.
SELECT COUNT(1)
FROM table_name
WHERE unique_key = value;

पहला विकल्प आपको कोई परिणाम या एक परिणाम नहीं देना चाहिए, दूसरी गणना शून्य या एक होनी चाहिए।

आपके द्वारा उपयोग किए जा रहे दस्तावेज़ कितने पुराने हैं? यद्यपि आपने अच्छी सलाह पढ़ी है, हाल के RDBMS के ऑप्टिमाइज़ेशन में अधिकांश क्वेरी ऑप्टिमाइज़र SELECT COUNT(*)वैसे भी हैं, इसलिए जब सिद्धांत (और पुराने डेटाबेस) में अंतर होता है, तो आपको अभ्यास में कोई अंतर नहीं देखना चाहिए।


1
मैं स्पष्ट करूंगा कि मैंने "कुंजी = मान" खंड के साथ "अद्वितीय कुंजी" का इरादा किया था, लेकिन इसके अलावा मैं अभी भी अपने उत्तर के पीछे हूं।
मार्टिन शेपेंडोन्क

1
ठीक है। उस आधार के साथ वास्तव में क्वेरी सिर्फ एक या शून्य रिकॉर्ड वापस आ जाएगी। BUT: प्रश्न एक अद्वितीय स्तंभ तक सीमित नहीं है। भी: दूसरी क्वेरी गणना (1) एक व्यावहारिक पीओवी से गिनती (*) के बराबर है।
मार्टिन बा

1
सवाल कहता है "ए रिकॉर्ड के अस्तित्व को सत्यापित करने का उचित तरीका क्या है"। मैंने व्याख्या की कि एकवचन के रूप में, जैसे: 1 रिकॉर्ड। काउंट (*) और काउंट (1) के बीच का अंतर मेरे जवाब से पहले से ही कवर है। मैं गिनती (1) को प्राथमिकता देता हूं क्योंकि यह एक विशिष्ट आरडीबीएमएस कार्यान्वयन पर निर्भर नहीं करता है।
मार्टिन शेपेंडकोंड

192

मैं गणना फ़ंक्शन का उपयोग बिल्कुल नहीं करना पसंद करूंगा:

IF [NOT] EXISTS ( SELECT 1 FROM MyTable WHERE ... )
     <do smth>

उदाहरण के लिए यदि आप जाँचना चाहते हैं कि क्या डेटाबेस में डालने से पहले उपयोगकर्ता मौजूद है तो क्वेरी इस तरह दिख सकती है:

IF NOT EXISTS ( SELECT 1 FROM Users WHERE FirstName = 'John' AND LastName = 'Smith' )
BEGIN
    INSERT INTO Users (FirstName, LastName) VALUES ('John', 'Smith')
END

सामान्य तौर पर हम इसका उपयोग करते हैं (सत्यापित) जब कुछ करना चाहते हैं, तो आपका उत्तर अधिक पूर्ण होता है।
अबनेर एस्कोसियो

टी-एसक्यूएल का उपयोग करके उल्लेख करने के लिए अच्छा है
ब्रोनक

20

आप उपयोग कर सकते हैं:

SELECT 1 FROM MyTable WHERE <MyCondition>

यदि स्थिति से मेल खाते कोई रिकॉर्ड नहीं है, तो परिणामी रिकॉर्डसेट खाली है।


क्या आपका मतलब TOP 1 था? -> (MyTable <<MyCondition> से शीर्ष 1 का चयन करें)
जैकब

6
नहीं, मेरा मतलब बिलकुल "1" है
Cătălin Piti

1
क्वेरी ऑप्टिमाइज़र को भी सक्षम करने के लिए कि आप पढ़े / शेष डेटासेट की आवश्यकता नहीं होगी, आपको चयन करना चाहिए शीर्ष 1 1 से ... कहां ... (या अपने
RDBS के

3
एक्ज़िस्ट्स ऑपरेटर स्वयं ही पूरी तरह से न्यूनतम जानकारी प्राप्त करने की कोशिश करता है, इसलिए TOP 1 के अतिरिक्त 5 वर्णों को क्वेरी आकार में जोड़ने के अलावा कुछ नहीं करता है। - sqlservercentral.com/blogs/sqlinthewild/2011/04/05/…
AquaAlex

13

अन्य उत्तर काफी अच्छे हैं, लेकिन यह अनावश्यक पंक्तियों की जाँच को रोकने के लिए LIMIT 1(या समकक्ष) जोड़ने के लिए भी उपयोगी होगा ।


3
यदि कोई "अस्तित्व की जाँच करें" क्वेरी एक पंक्ति से अधिक वापस आती है, तो मुझे लगता है कि परिणाम की संख्या लिमिट-इंग के बजाय अपने WHERE क्लॉज को दोबारा जांचना अधिक उपयोगी है।
बजे मार्टिन शेपेंडोन्क

2
मुझे लगता है कि सीमा का उपयोग Oracle में किया जाता है न कि SQL Server में
शांतनु गुप्ता

7
मैं उस मामले पर विचार कर रहा हूं जहां वे वैध रूप से कई पंक्तियां हो सकती हैं - जहां सवाल यह है: "क्या ऐसी (एक या अधिक) पंक्तियां हैं जो इस स्थिति को संतुष्ट करती हैं?" उस स्थिति में, आप उन सभी को नहीं देखना चाहते, बस एक।
जेसीडब्ल्यू

1
@ शांतनु - मुझे पता है, इसीलिए मैंने (बहुत से) en.wikipedia आर्टिकल को अन्य रूपों के बारे में समझा।
जेसीडब्ल्यू

11
SELECT COUNT(1) FROM MyTable WHERE ...

सभी रिकॉर्ड के माध्यम से लूप होगा। यही कारण है कि रिकॉर्ड अस्तित्व के लिए इसका उपयोग करना बुरा है।

मै इस्तेमाल करूंगा

SELECT TOP 1 * FROM MyTable WHERE ...

1 रिकॉर्ड खोजने के बाद, यह लूप को समाप्त कर देगा।


SELECT TOP 1वसीयत के मामले में , यह वास्तव में एक को खोजने के बाद समाप्त हो जाता है या क्या यह सभी को यह पता लगाने में सक्षम है कि कौन सा टॉप है?
एरिक एच।

3
पुनश्च: सुनिश्चित करने के लिए मैं हमेशाIF EXISTS (SELECT TOP 1 1 FROM ... WHERE ..)
Eirik H

स्टार ऑपरेटर DBMS को केवल इंडेक्स (es) के बजाय क्लस्टर इंडेक्स तक पहुंचने के लिए बाध्य करेगा, जो आपकी सम्मिलित स्थिति के लिए आवश्यक होगा। इसलिए परिणाम के रूप में एक निरंतर वलुआ का उपयोग करना बेहतर है, अर्थात शीर्ष 1 1 का चयन करें .... जो कि 1 या DB-Null लौटेगा, इस शर्त पर निर्भर करता है कि यह मैच है या नहीं।
eFloh

यह अच्छा है। मैं पहले वाले को पसंद करता हूं।
isxaker

10

आप उपयोग कर सकते हैं:

SELECT COUNT(1) FROM MyTable WHERE ... 

या

WHERE [NOT] EXISTS 
( SELECT 1 FROM MyTable WHERE ... )

यह अधिक कुशल होगा SELECT *क्योंकि आप केवल प्रत्येक पंक्ति के लिए मान 1 का चयन कर रहे हैं, बजाय सभी क्षेत्रों के।

COUNT (*) और COUNT (स्तंभ नाम) के बीच एक सूक्ष्म अंतर भी है:

  • COUNT(*) nulls सहित सभी पंक्तियों की गणना करेगा
  • COUNT(column name)केवल कॉलम नाम की गैर अशक्त घटनाओं की गणना करेगा

2
आप गलत धारणा बना रहे हैं कि एक DBMS किसी भी तरह उन सभी स्तंभों की जाँच करेगा। प्रदर्शन के बीच count(1)का count(*)अंतर केवल सबसे अधिक मस्तिष्क-मृत डीबीएमएस में भिन्न होगा।
पैक्सडिब्लो

2
नहीं, मैं कह रहा हूं कि आप वास्तव में कार्यान्वयन विवरण पर भरोसा कर रहे हैं जब आप कहते हैं कि यह अधिक कुशल होगा। यदि आप वास्तव में यह सुनिश्चित करना चाहते हैं कि आपको सर्वश्रेष्ठ प्रदर्शन मिले, तो आपको इसे प्रतिनिधि डेटा का उपयोग करके विशिष्ट कार्यान्वयन के लिए प्रोफाइल करना चाहिए, या बस इसके बारे में पूरी तरह से भूल जाना चाहिए। और कुछ भी संभावित रूप से भ्रामक है, और DB2 से MySQL तक चलते समय (उदाहरण के लिए) काफी बदल सकता है।
paxdiablo

1
मैं यह स्पष्ट करना चाहता हूं कि मैं आपका जवाब नहीं दे रहा हूं। यह है उपयोगी। मेरे द्वारा जारी किए जाने वाले एकमात्र बिट दक्षता का दावा है क्योंकि हम कर रहे हैं DB2 / z में मूल्यांकन है, और पाया कि count(*)और के बीच कोई वास्तविक अंतर नहीं है count(1)। चाहे वह अन्य DBMS के लिए हो ', मैं नहीं कह सकता।
पैक्सडिब्लो

3
"और कुछ भी संभावित रूप से भ्रामक है, और DB2 से MySQL के लिए (उदाहरण के लिए) चलते समय काफी बदल सकता है" आपको SELECT 1 में कार्यान्वयन अंतर की तुलना में DBMS को स्थानांतरित करते समय SELECT COUNT (*) के प्रदर्शन में गिरावट की संभावना है। या COUNT (1)। मैं कोड लिखने में दृढ़ विश्वास रखता हूं, जो आपके इच्छित व्यवहार के लिए डिफ़ॉल्ट रूप से ऑप्टिमाइज़र या कंपाइलर पर निर्भर होने के बजाय, जो आप प्राप्त करना चाहते हैं, वह बिल्कुल स्पष्ट रूप से व्यक्त करता है।
विंस्टन स्मिथ

1
भ्रामक कथन "COUNT (*)" का अर्थ है 'पंक्तियों की पूर्ण विराम गणना'। इसमें किसी विशेष कॉलम तक पहुंच की आवश्यकता नहीं है। और ज्यादातर मामलों में पंक्ति तक पहुंच की आवश्यकता भी नहीं होगी क्योंकि गिनती किसी भी अद्वितीय सूचकांक के लिए पर्याप्त है।
जेम्स एंडरसन

9

आप उपयोग कर सकते हैं:

SELECT 1 FROM MyTable WHERE... LIMIT 1

select 1अनावश्यक क्षेत्रों की जाँच को रोकने के लिए उपयोग करें ।

LIMIT 1 अनावश्यक पंक्तियों की जाँच को रोकने के लिए उपयोग करें ।


3
अच्छी बात है, लेकिन सीमा MySQL और PostgreSQL पर काम करती है, SQL सर्वर पर शीर्ष काम करता है, आपको इसे अपने जवाब पर ध्यान देना चाहिए
लियो गुरडियन

0

मैं इस तरह का उपयोग कर रहा हूँ:

IIF(EXISTS (SELECT TOP 1 1 
                FROM Users 
                WHERE FirstName = 'John'), 1, 0) AS DoesJohnExist

0

दूसरा विकल्प:

SELECT CASE
    WHEN EXISTS (
        SELECT 1
        FROM [MyTable] AS [MyRecord])
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.