यदि आप अब तक जवाब एक साथ रखते हैं, तो सफाई करें और सुधार करें, आप इस बेहतर क्वेरी पर पहुंचेंगे:
UPDATE sales
SET status = 'ACTIVE'
WHERE (saleprice, saledate) IN (
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING count(*) = 1
);
जो दोनों में से बहुत तेज है। कारक 10 - 15 द्वारा वर्तमान में स्वीकार किए गए उत्तर का प्रदर्शन Nukes (PostgreSQL 8.4 और 9.1 पर मेरे परीक्षणों में)।
लेकिन यह अभी भी इष्टतम से दूर है। NOT EXISTS
बेहतर प्रदर्शन के लिए एक (एंटी-) सेमी-जॉइन का उपयोग करें । EXISTS
मानक SQL है, हमेशा के लिए (कम से कम PostgreSQL 7.2 के बाद से, इस सवाल के पूछे जाने से बहुत पहले) के आसपास है और प्रस्तुत आवश्यकताओं को फिट बैठता है:
UPDATE sales s
SET status = 'ACTIVE'
WHERE NOT EXISTS (
SELECT FROM sales s1 -- SELECT list can be empty for EXISTS
WHERE s.saleprice = s1.saleprice
AND s.saledate = s1.saledate
AND s.id <> s1.id -- except for row itself
)
AND s.status IS DISTINCT FROM 'ACTIVE'; -- avoid empty updates. see below
db <> यहाँ
field पुरानी SQL फ़ेल्ड
पंक्ति की पहचान करने के लिए अद्वितीय कुंजी
यदि आपके पास तालिका ( id
उदाहरण में) के लिए एक प्राथमिक या अद्वितीय कुंजी नहीं है , तो आप ctid
इस क्वेरी के उद्देश्य के लिए सिस्टम कॉलम के साथ स्थानापन्न कर सकते हैं (लेकिन कुछ अन्य उद्देश्यों के लिए नहीं):
AND s1.ctid <> s.ctid
प्रत्येक तालिका में एक प्राथमिक कुंजी होनी चाहिए। यदि आपके पास अभी तक एक नहीं है, तो उसे जोड़ें। मैं 10+ पोस्टग्रेज में एक serial
या एक IDENTITY
कॉलम सुझाता हूं ।
सम्बंधित:
यह कैसे तेज है?
EXISTS
एंटी-सेमी-ज्वाइन में सबकुछ का मूल्यांकन जैसे ही पहली बार पाया जाता है (आगे देखने का कोई मतलब नहीं) बंद कर सकता है। कुछ डुप्लिकेट के साथ एक आधार तालिका के लिए यह केवल अपेक्षाकृत अधिक कुशल है। डुप्लिकेट के बहुत सारे के साथ इस हो जाता है जिस तरह से और अधिक कुशल।
खाली अपडेट को छोड़ दें
उन पंक्तियों के लिए जिनके पास पहले से ही status = 'ACTIVE'
यह अपडेट है, कुछ भी नहीं बदलेगा, लेकिन फिर भी पूरी लागत पर एक नया पंक्ति संस्करण डालें (मामूली अपवाद लागू होते हैं)। आम तौर पर, आप यह नहीं चाहते हैं। इससे WHERE
बचने के लिए ऊपर दी गई एक और शर्त जोड़ें और इसे और तेज़ करें:
यदि status
परिभाषित किया गया है NOT NULL
, तो आप इसे सरल कर सकते हैं:
AND status <> 'ACTIVE';
कॉलम के डेटा प्रकार को <>
ऑपरेटर का समर्थन करना चाहिए । कुछ प्रकार की तरह json
नहीं है। देख:
NULL हैंडलिंग में सूक्ष्म अंतर
यह क्वेरी ( जोएल द्वारा वर्तमान में स्वीकृत उत्तर के विपरीत ) NULL मूल्यों को समान नहीं मानती है। निम्नलिखित दो पंक्तियाँ (saleprice, saledate)
"विशिष्ट" के रूप में योग्य होंगी (हालांकि मानव आंख के समान दिखती हैं):
(123, NULL)
(123, NULL)
इसके अलावा एक अद्वितीय सूचकांक में और लगभग कहीं भी गुजरता है, क्योंकि NULL मान SQL मानक के अनुसार समान की तुलना नहीं करते हैं। देख:
OTOH, GROUP BY
, DISTINCT
या DISTINCT ON ()
समकक्ष के रूप में इलाज शून्य मान। आप जो हासिल करना चाहते हैं, उसके आधार पर एक उपयुक्त क्वेरी शैली का उपयोग करें। NULL तुलना करने के लिए आप इस तेज़ क्वेरी का उपयोग किसी भी या सभी तुलनाओं के IS NOT DISTINCT FROM
बजाय कर सकते हैं =
। अधिक:
यदि तुलना किए जा रहे सभी कॉलम परिभाषित किए गए हैं NOT NULL
, तो असहमति के लिए कोई जगह नहीं है।