केवल एक कॉलम के लिए DISTINCT


156

मान लीजिए कि मेरे पास निम्नलिखित प्रश्न हैं।

SELECT ID, Email, ProductName, ProductModel FROM Products

मैं इसे कैसे संशोधित कर सकता हूं ताकि यह कोई डुप्लिकेट ईमेल न लौटाए?

दूसरे शब्दों में, जब कई पंक्तियों में एक ही ईमेल होता है, तो मैं चाहता हूं कि परिणाम केवल उन पंक्तियों में से एक को शामिल करें (अधिमानतः पिछले एक)। अन्य कॉलम में डुप्लिकेट को अनुमति दी जानी चाहिए।

पूरी पंक्तियों पर काम करना पसंद करते हैं DISTINCTऔर GROUP BYदिखाई देते हैं। इसलिए मुझे यकीन नहीं है कि यह कैसे होगा।


2
ठीक है, आपको पार्टिशन का उपयोग करने की आवश्यकता है या दो चयनित बयानों का उपयोग करने की आवश्यकता है?
कार्नेकोड

और अगर एक ही ईमेल के साथ 2 पंक्तियाँ हैं, लेकिन अलग-अलग ProductName हैं तो क्या दिखाया जाना चाहिए? (अधिमानतः पिछले एक) स्पष्ट नहीं है। आखिर किसके आदेश से?
ypercube y

@ypercube जैसा कि प्रश्न में कहा गया है, अधिमानतः अंतिम है। हालाँकि, यह वास्तव में मेरे लिए महत्वपूर्ण नहीं है। मुझे बस उनमें से एक चाहिए।
जोनाथन वुड

1
आप निम्नलिखित प्रश्नों को देख सकते हैं: प्रश्न 1 , प्रश्न 2 या प्रश्न 3
मैरिएन

आप इसका उपयोग क्यों नहीं कर सकते: उत्पादों का चयन ईमेल, आईडी, उत्पाद नाम, उत्पाद से उत्पाद का नाम?
रिक हेंडरसन

जवाबों:


186

यदि आप SQL Server 2005 या इसके बाद के संस्करण का उपयोग कर रहे हैं:

SELECT *
  FROM (
                SELECT  ID, 
                        Email, 
                        ProductName, 
                        ProductModel,
                        ROW_NUMBER() OVER(PARTITION BY Email ORDER BY ID DESC) rn
                    FROM Products
              ) a
WHERE rn = 1

संपादित करें: उदाहरण जहां एक खंड का उपयोग कर:

SELECT *
  FROM (
                SELECT  ID, 
                        Email, 
                        ProductName, 
                        ProductModel,
                        ROW_NUMBER() OVER(PARTITION BY Email ORDER BY ID DESC) rn
                    FROM Products
                   WHERE ProductModel = 2
                     AND ProductName LIKE 'CYBER%'

              ) a
WHERE rn = 1

4
मुझे इस विभाजन खंड की जांच करनी चाहिए, इसे पहले कभी कार्रवाई में नहीं देखा था। उदाहरण के लिए धन्यवाद
लोरेन वीएस

@Cybernate एक जटिलता: मेरे भीतर SELECTएक WHEREशर्त की जरूरत है । मुझे लगता है कि पंक्ति संख्या तालिका में सभी पंक्तियों को दी जाएगी। यह वाक्य रचना मेरे से थोड़ा परे है। अद्यतन का कोई भी मौका जो एक विशेष ईमेल के साथ एक पंक्ति की गारंटी देगा जो WHEREशर्त को पूरा करता है?
जोनाथन वुड

1
आप जोड़ सकते हैं कि आंतरिक वर्ग के लिए क्लॉज कहां है। मैं अपने लैपटॉप
चंदू

1
जहां क्लॉज का उपयोग करके एक नमूने के साथ पोस्ट अपडेट किया गया।
चंदू

1
मुझे यह काम सही ढंग से तभी मिलता है जब मेरी क्वेरी में कोई JOIN एस हो । जैसे ही मेरे पास है JOIN, ROW_NUMBER"1" की तुलना में बहुत अधिक मान देता है।
ऊव कीम

10

यह SQL सर्वर 2005+ मानता है और "अंतिम" की आपकी परिभाषा किसी दिए गए ईमेल के लिए अधिकतम PK है

WITH CTE AS
(
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel, 
       ROW_NUMBER() OVER (PARTITION BY Email ORDER BY ID DESC) AS RowNumber 
FROM   Products
)
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel
FROM CTE 
WHERE RowNumber = 1

6

जब आप DISTINCTइसके बारे में एक अलग पंक्ति के रूप में सोचते हैं, तो कॉलम नहीं। यह केवल उन पंक्तियों को लौटाएगा जहां कॉलम बिल्कुल समान रूप से मेल नहीं खाते हैं।

SELECT DISTINCT ID, Email, ProductName, ProductModel
FROM Products

----------------------
1 | something@something.com | ProductName1 | ProductModel1
2 | something@something.com | ProductName1 | ProductModel1

क्वेरी दोनों पंक्तियों को लौटाएगी क्योंकि IDस्तंभ अलग है। मैं मान रहा हूं कि IDस्तंभ एक IDENTITYस्तंभ है जो बढ़ रहा है, यदि आप अंतिम को वापस करना चाहते हैं तो मैं कुछ इस तरह की सलाह देता हूं:

SELECT DISTINCT TOP 1 ID, Email, ProductName, ProductModel
FROM Products
ORDER BY ID DESC

यह TOP 1केवल पहला रिकॉर्ड लौटाएगा, इसे IDअवरोही क्रम से आदेश देकर पहले अंतिम पंक्ति के साथ परिणाम लौटाएगा। यह आपको आखिरी रिकॉर्ड देगा।


2
जैसा कि प्रश्न में कहा गया है, मैं देखता हूं कि DISTINCT पूरी पंक्ति पर काम करता है। मैं ऐसा करना चाहता हूं जैसा कि आप ऊपर सुझाव देते हैं, लेकिन हर बार परिणामों में ईमेल को दोहराया जाता है (सिर्फ एक बार नहीं)।
जोनाथन वुड

उस मामले में मैं @Cybernate जवाब के साथ जाने की सलाह दूंगा। आपको वही करना चाहिए जो आपको चाहिए।
jon3laze

4

आप ग्रुप बाय फंक्शन का उपयोग करके इसे खत्म कर सकते हैं

SELECT ID, Email, ProductName, ProductModel FROM Products GROUP BY Email


16
कॉलम 'Products.ID' का चयन सूची में अमान्य है क्योंकि यह एक समुच्चय फ़ंक्शन या ग्रुप बाय क्लॉज़ में निहित नहीं है।
पालोटा

2
यह अन्य कॉलम के लिए MAX (ID), MAX (ProductName), MAX (ProductModel) जैसे कुछ का उपयोग किए बिना काम नहीं करता है
avl_sweden

2
पोस्टग्रेज में, आपको केवल उस कॉलम पर समुच्चय फ़ंक्शन की आवश्यकता होती है, जिसका उपयोग समूह में खंड, जैसे SELECT id, max(email) AS email FROM tbl GROUP by email। SQL सर्वर में SELECTक्लॉज के सभी कॉलम एक कुल फ़ंक्शन में होने चाहिए। यह मुझे हर बार काटता है जब मैं वापस जाता हूं।
ब्रूस पियर्स

यह कभी काम नहीं करेगा। यह एक बुरा समाधान है
Dan AS

1

एक्सेस के लिए, आप यहां मौजूद SQL Select क्वेरी का उपयोग कर सकते हैं:

उदाहरण के लिए आपके पास यह तालिका है:

CLIENTE || NOMBRES || मेल

888 || T800 ARNOLD || t800.arnold@cyberdyne.com

123 || जॉन कोन्नर || s.connor@skynet.com

125 || SARAH CONNOR ||s.connor@skynet.com

और आपको केवल अलग मेल का चयन करने की आवश्यकता है। आप इसे इसके साथ कर सकते हैं:

SQL चयन:

SELECT MAX(p.CLIENTE) AS ID_CLIENTE
, (SELECT TOP 1 x.NOMBRES 
    FROM Rep_Pre_Ene_MUESTRA AS x 
    WHERE x.MAIL=p.MAIL 
     AND x.CLIENTE=(SELECT MAX(l.CLIENTE) FROM Rep_Pre_Ene_MUESTRA AS l WHERE x.MAIL=l.MAIL)) AS NOMBRE, 
p.MAIL
FROM Rep_Pre_Ene_MUESTRA AS p
GROUP BY p.MAIL;

आप इसका उपयोग अधिकतम आईडी, उस अधिकतम आईडी के संवाददाता नाम का चयन करने के लिए कर सकते हैं, आप इस तरह से कोई अन्य विशेषता जोड़ सकते हैं। फिर अंत में आप फ़िल्टर करने के लिए अलग कॉलम रखते हैं और आप इसे केवल उस अंतिम अलग कॉलम के साथ समूहित करते हैं।

यह आपको संवाददाता डेटा के साथ अधिकतम आईडी लाएगा, आप मिनट या किसी भी अन्य कार्यों का उपयोग कर सकते हैं और आप उस फ़ंक्शन को उप-प्रश्नों के लिए दोहरा सकते हैं।

यह चयन वापस आएगा:

CLIENTE || NOMBRES || मेल

888 || T800 ARNOLD || t800.arnold@cyberdyne.com

125 || SARAH CONNOR ||s.connor@skynet.com

याद रखें कि आपके द्वारा चुने गए कॉलमों को अनुक्रमित करना और अलग-अलग कॉलम में ऊपरी मामले या निचले मामले में सभी संख्यात्मक डेटा नहीं होना चाहिए, अन्यथा यह काम नहीं करेगा। यह केवल एक पंजीकृत मेल के साथ ही काम करेगा। हैप्पी कोडिंग !!!


0

संपूर्ण पंक्तियों पर कारण DISTINCTऔर GROUP BYकार्य यह है कि आपकी क्वेरी संपूर्ण पंक्तियों को लौटाती है।

आपको समझने में मदद करने के लिए: हाथ से लिखने की कोशिश करें कि क्वेरी क्या वापस आनी चाहिए और आप देखेंगे कि यह अस्पष्ट है कि गैर-डुप्लिकेट किए गए कॉलम में क्या रखा जाए।

यदि आप सचमुच अन्य स्तंभों में क्या है, इसकी परवाह नहीं करते हैं, तो उन्हें वापस न करें। प्रत्येक ई-मेल पते के लिए एक यादृच्छिक पंक्ति वापस करना मेरे लिए थोड़ा बेकार लगता है।


@ जॉनफिक्स मैं पूरी पंक्तियों को वापस करना चाहता हूं। मैं नहीं चाहता कि पंक्तियों को लौटाया जाए जब परिणाम पहले से ही ईमेल स्तंभ में उसी मान के साथ एक पंक्ति शामिल करें।
जोनाथन वुड

तो यह कैसे तय करना चाहिए कि किसको वापस लौटना है? क्या आप वास्तव में एक ऐसी क्वेरी चाहते हैं जो प्रत्येक ई-मेल के लिए एक मनमानी पंक्ति लौटाए। यह वास्तव में बदबू आ रही है जैसे आपको उस समस्या पर फिर से विचार करने की आवश्यकता हो सकती है जिसे आप हल करने की कोशिश कर रहे हैं। लगभग हर बार मुझे यह सवाल पूछा गया है (और यह बहुत ऊपर आता है) यह पता चला है कि डेवलपर ने इस व्यवहार के लिए ऐप में परिणामों के माध्यम से नहीं सोचा है।
जॉन एफएक्स 16'11

6
मुझे आपके तर्क के बाद वास्तव में परेशानी हो रही है। जैसा कि प्रश्न में कहा गया है, मैं पिछले एक (आईडी द्वारा क्रमबद्ध) को प्राथमिकता दूंगा। हां, अगर यह एक यादृच्छिक पंक्ति का चयन करता है जो ठीक होगा। और, हां, मैंने इसके बारे में सोचा है।
जोनाथन वुड


-2

इसे इस्तेमाल करे:

SELECT ID, Email, ProductName, ProductModel FROM Products WHERE ID IN (SELECT MAX(ID) FROM Products GROUP BY Email)

2
हमें इसकी कोशिश क्यों करनी चाहिए? यह पिछले 8 वर्षों में यहां पोस्ट किए गए अन्य उत्तरों से बेहतर क्यों है? यदि आप समस्या को हल करने के लिए एक बेहतर तरीका साझा करना चाहते हैं, तो आपको यह समझाने की आवश्यकता है कि आप इसे क्यों सुझाते हैं।
धर्मन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.