एक ही चयन कथन में DISTINCT और ORDER BY का उपयोग कैसे करें?


117

निम्नलिखित कथन को निष्पादित करने के बाद:

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

मुझे डेटाबेस से निम्नलिखित मान मिल रहे हैं:

test3
test3
bildung
test4
test3
test2
test1

लेकिन मैं इस तरह से हटाए गए डुप्लिकेट चाहता हूं:

bildung
test4
test3
test2
test1

मैंने DISTINCT का उपयोग करने की कोशिश की, लेकिन यह एक कथन में ORDER BY के साथ काम नहीं करता है। कृपया मदद कीजिए।

जरूरी:

  1. मैंने इसके साथ कोशिश की:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC

    यह काम नहीं करता है।

  2. क्रिएशनडेट द्वारा आदेश बहुत महत्वपूर्ण है।


1
यह कैसे काम नहीं करता है? गलत उत्पादन?
फेडरन

जवाबों:


195

समस्या यह है कि इसमें उपयोग किए गए कॉलम ORDER BYनिर्दिष्ट नहीं हैं DISTINCT। ऐसा करने के लिए, आपको काम करने के लिए एक समग्र फ़ंक्शन का उपयोग GROUP BYकरना होगा और DISTINCTकाम करने के लिए उपयोग करना होगा।

कुछ इस तरह की कोशिश करो:

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category

99
यदि आपको श्रेणी के आधार पर समूह बनाने की आवश्यकता नहीं है, तो आपको DISTINCT कीवर्ड की भी आवश्यकता नहीं है।
MatBailie

18

विस्तारित सॉर्ट कुंजी कॉलम

कारण यह है कि आप जो काम नहीं करना चाहते हैं, वह SQL के संचालन के तार्किक क्रम के कारण है , जो आपकी पहली क्वेरी के लिए है, (सरल):

  • FROM MonitoringJob
  • SELECT Category, CreationDateयानी एक तथाकथित विस्तारित सॉर्ट कुंजी कॉलम जोड़ें
  • ORDER BY CreationDate DESC
  • SELECT Categoryयानी परिणाम से फिर से विस्तारित सॉर्ट कुंजी कॉलम को हटा दें ।

इसलिए, SQL मानक विस्तारित सॉर्ट कुंजी कॉलम सुविधा के लिए धन्यवाद , यह कुछ ऐसा है जो SELECTखंड में नहीं है, द्वारा आदेश देना पूरी तरह से संभव है , क्योंकि इसे अस्थायी रूप से पर्दे के पीछे जोड़ा जा रहा है।

तो, यह काम क्यों नहीं करता है DISTINCT?

हम जोड़ देते हैं तो DISTINCTआपरेशन, यह के बीच जोड़ा जाएगा SELECTऔर ORDER BY:

  • FROM MonitoringJob
  • SELECT Category, CreationDate
  • DISTINCT
  • ORDER BY CreationDate DESC
  • SELECT Category

लेकिन अब, विस्तारित सॉर्ट कुंजी कॉलम के साथ CreationDate , DISTINCTऑपरेशन के शब्दार्थ को बदल दिया गया है, इसलिए परिणाम अब समान नहीं होगा। यह वह नहीं है जो हम चाहते हैं, इसलिए SQL मानक और सभी उचित डेटाबेस इस उपयोग को मना करते हैं।

समाधान

इसे निम्न प्रकार से मानक वाक्यविन्यास के साथ अनुकरण किया जा सकता है

SELECT Category
FROM (
  SELECT Category, MAX(CreationDate) AS CreationDate
  FROM MonitoringJob
  GROUP BY Category
) t
ORDER BY CreationDate DESC

या, बस (इस मामले में), जैसा कि प्रुट्सवॉन्डर द्वारा भी दिखाया गया है

SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC

मैंने यहाँ विस्तार से SQL DISTINCT और ORDER BY के बारे में ब्लॉग किया है


1
मुझे लगता है कि आप गलत हैं कि कैसे DISTINCT ONकाम करता है और यकीन है कि यह यहाँ मदद नहीं करता है। कोष्ठक में अभिव्यक्ति वह है जिसका उपयोग विशिष्टता (समूहन स्थिति) निर्धारित करने के लिए किया जाता है। यदि समान के साथ अलग-अलग श्रेणियां हैं, CreationDateतो उनमें से केवल एक ही परिणाम में दिखाई देगा! चूँकि मैं सोच रहा था कि शायद मैं किसी तरह गलत था, इसलिए मैंने आपके ब्लॉग पोस्ट में डबल-चेक करने के लिए उदाहरण डेटाबेस भी लोड किया: DISTINCT ONआपके द्वारा दी गई क्वेरी ने कुल 1000 परिणाम (बहुत सारे डुप्लिकेट lengths के साथ) पैदा किए, जबकि नीचे दिए गए क्वेरी केवल 140 (अद्वितीय) मूल्य।
आभास

@ इंकिंग: आपके समय के लिए धन्यवाद। ओपी स्पष्ट रूप से "डुप्लिकेट्स" को हटा देना चाहता है। ओपी का शब्दांकन देखें "लेकिन मैं चाहता हूं कि इस तरह से डुप्लिकेट हटा दिए जाएं" । आपने शायद मेरे ब्लॉग पोस्ट के प्रश्नों को कॉपी करते समय गलती की है। दो प्रश्न हैं, एक का उपयोग करता है DISTINCT(कोई ON) और एक का उपयोग करता है DISTINCT ON। कृपया देखें कि उत्तरार्द्ध स्पष्ट रूप से डुप्लिकेट लंबाई नहीं हटाता है, लेकिन डुप्लिकेट शीर्षक। मुझे लगता है कि यहां मेरा जवाब पूरी तरह से सही है।
लुकास एडर

1
मेरा कहना है कि आपकी DISTINCT ONस्थिति गलत स्थिति का उपयोग करके डुप्लिकेट को हटा रही है। आपके ब्लॉग पोस्ट में DISTINCT ONक्वेरी वास्तव में डुप्लिकेट शीर्षकों को हटाती है , हालांकि DISTINCTइसके ऊपर की क्वेरी और इसके नीचे की क्वेरी (जिसके लिए आप दावा करते हैं कि यह "सिंटैक्स शुगर" है) दोनों डुप्लिकेट लंबाई को हटाते हैं , क्योंकि संभवतः यह संपूर्ण लक्ष्य है। यही बात यहां लागू होती है: ओपी डुप्लिकेट श्रेणियां हटाता है, डुप्लिकेट क्रिएशनडेट्स नहीं जैसा कि DISTINCT ONक्वेरी करता है। यदि आप अभी भी मुझ पर विश्वास नहीं करते हैं, तो अपने लिए परीक्षण करें।
आभास

6

यदि MAX (क्रिएशनडेट) का आउटपुट नहीं चाहिए - जैसे मूल प्रश्न के उदाहरण में - केवल एक ही उत्तर प्रशांत गुप्ता के उत्तर का दूसरा कथन है:

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

स्पष्टीकरण: आप इनलाइन फ़ंक्शन में ORDER BY खंड का उपयोग नहीं कर सकते हैं, इसलिए Prutswonder के उत्तर में कथन इस मामले में उपयोग करने योग्य नहीं है, आप इसके चारों ओर एक बाहरी चयन नहीं कर सकते हैं और MAX (CreationDate) भाग को छोड़ सकते हैं।


2

यदि आप [श्रेणी] और [क्रिएशनडाइट] कॉलम के मान चाहते हैं, तो इस कोड का उपयोग करें

SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob] 
             GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

या इस कोड का उपयोग करें, यदि आप केवल [श्रेणी] कॉलम के मान चाहते हैं।

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

आपके पास सभी विशिष्ट रिकॉर्ड होंगे जो आप कभी भी चाहते हैं।


उन ब्रेसिज़ [] पूरी तरह से भ्रमित हैं ... क्या यह वैध SQL सिंटैक्स है?
m13r

1
कोष्ठक खोजशब्द से बचने के लिए हैं, जैसे कि आदेश, घटना, इत्यादि, यदि आपके पास (उदाहरण के लिए) आपकी तालिका में एक स्तंभ है, जिसे Eventआप लिख सकते हैं कि आप SQL को पार्स एरर को रोकने के [Event]बजाय लिख सकते हैं Event
बेन मैक्सफील्ड

1

2) क्रिएशनडेट द्वारा आदेश बहुत महत्वपूर्ण है

मूल परिणामों से संकेत मिलता है कि "test3" के कई परिणाम थे ...

ग्रुप बी में डुप्लिकेट को हटाने के लिए मैक्स का उपयोग करना शुरू करना बहुत आसान है ... और भूल जाओ या अंतर्निहित प्रश्न पर ध्यान न दें ...

ओपी संभवतः यह महसूस करता है कि मैक्स का उपयोग उसे अंतिम "बनाया" दे रहा था और मिन का उपयोग करके पहला "बनाया" देगा ...


3
यह वास्तव में प्रश्न का उत्तर नहीं देता है, यह प्रश्न के उत्तर के MAXरूप में अकेले खड़े होने वाले किसी चीज़ के बजाय अन्य उत्तरदाता के उपयोगों पर एक टिप्पणी प्रतीत होता है ।
डेविडेवडे

0
if object_id ('tempdb..#tempreport') is not null
begin  
drop table #tempreport
end 
create table #tempreport (
Category  nvarchar(510),
CreationDate smallint )
insert into #tempreport 
select distinct Category from MonitoringJob (nolock) 
select * from #tempreport  ORDER BY CreationDate DESC

0

उपशम द्वारा, यह काम करना चाहिए:

    SELECT distinct(Category) from MonitoringJob  where Category in(select Category from MonitoringJob order by CreationDate desc);

उम्म ... मुझे नहीं लगता कि यह होगा। बाहरी चयन सॉर्ट नहीं किया गया है।
होसम एल-दीन

यह काम नहीं करेगा, मैं यहाँ हूँ क्योंकि यह काम नहीं कर रहा है
अमीरेज़ा

-1

डिस्टिंक्ट आरोही क्रम में रिकॉर्ड सॉर्ट करेगा। यदि आप अवरोही क्रम में उपयोग करना चाहते हैं:

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

यदि आप क्रिएशनडैट फ़ील्ड के आधार पर रिकॉर्ड को क्रमबद्ध करना चाहते हैं तो यह फ़ील्ड चयनित कथन में होनी चाहिए:

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC

12
यह निष्पादित करेगा लेकिन ओपी को जो चाहिए वह नहीं देगा। OP अलग-अलग श्रेणियाँ चाहता है, श्रेणी और CreateDate के अलग-अलग संयोजन नहीं। यह कोड एक ही श्रेणी के कई उदाहरण पेश कर सकता है, प्रत्येक में अलग-अलग क्रिएशनडेट मान हो सकते हैं।
MatBailie

-1

आप सीटीई का उपयोग कर सकते हैं:

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC

-3

अगला प्रयास करें, लेकिन यह विशाल डेटा के लिए उपयोगी नहीं है ...

SELECT DISTINCT Cat FROM (
  SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);

4
"ORDER BY खंड, इनलाइन फ़ंक्शंस, व्युत्पन्न टेबल, सबक्वेरीज़ और सामान्य तालिका अभिव्यक्तियों में अमान्य है, जब तक कि TOP या XML के लिए भी निर्दिष्ट नहीं किया जाता है।"
TechplexEngineer

यह काम नहीं करता है क्योंकि आपने आदेश पर कॉलम क्रिएशनडेट को निर्दिष्ट नहीं किया है।
मौरो बिलोती

1
@TechplexEngineer आपकी टिप्पणी गलत है। ORDER BYउप-प्रश्नों में उपयोग करना सर्वथा मान्य है। और किसी ने आपकी गलत टिप्पणी को भी गलत ठहराया।
रशिल हिलन

मैं यह कोशिश कर रहा हूं और @TechplexEngineer के साथ समान त्रुटि हो रही है। मैं जब केस के साथ कस्टम ऑर्डर का उपयोग कर रहा हूं।
एगे बेयार्क

-4

इसे इस तरह से आंतरिक क्वेरी का उपयोग करके किया जा सकता है

$query = "SELECT * 
            FROM (SELECT Category  
                FROM currency_rates                 
                ORDER BY id DESC) as rows               
            GROUP BY currency";

-5
SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC

2
मुझे सृजन तिथि के अनुसार इसकी आवश्यकता है !! यह बहुत महत्वपूर्ण है
rr

तो क्या उस कॉलम को जोड़ना असंभव है जिसे आप स्वयं ऑर्डर करना चाहते हैं? आपके उदाहरण से प्रदर्शित प्रविष्टियों ने वर्णानुक्रम में आदेश दिया। यदि आपको बनाई गई तारीख तक ऑर्डर करने की आवश्यकता है, तो बस इसे जोड़ें। यह वास्तव में उतना मुश्किल नहीं है।
फ्यूरिकेन

8
-1: ओपी ने कोशिश की, यह काम नहीं किया, क्योंकि यह असंभव है और आपने स्पष्ट रूप से ओपी का संरक्षण करते समय उस तथ्य को नजरअंदाज कर दिया था। मुद्दा यह है कि DISTINCT ऑपरेटर एक ही श्रेणी के मूल्य के साथ कई रिकॉर्ड्स को समेटेगा, प्रत्येक संभावित अलग-अलग तारीखों के साथ। इस प्रकार यह DISTINCT का उपयोग करते समय तार्किक रूप से असंभव है। यह DISTINCT के बजाय GROUP BY को आवश्यक तर्क देता है, जिससे निर्माण तिथि पर कुल (MAX) की अनुमति मिलती है।
MatBailie

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

8
आप सीधे CreatDate फ़ील्ड को जोड़ने का सुझाव देते हैं, यहां तक ​​कि "यह वास्तव में उतना मुश्किल नहीं है"। ऐसा करने से विकृत SQL का उत्पादन होता है। आपको ओपी को संरक्षण देने के लिए -1 मिला, ओपी को उस बयान पर वापस लेने की सलाह देना जो वह मूल रूप से पोस्ट किया था, और DISTINCT के बीच विवाद को नोटिस करने में विफल रहा और DISTINCT में नहीं एक क्षेत्र द्वारा आदेश दिया गया। इसके अतिरिक्त, 'b' 't' से पहले आता है, और '1' '4' से पहले आता है, इस प्रकार ओपी द्वारा दिए गए परिणाम स्पष्ट रूप से वर्णानुक्रम में नहीं होते हैं। हो सकता है कि मैं आपकी खुद की सलाह मान लूँ: अगली बार (और अधिक ध्यान से पढ़ें)।
MatBailie
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.