SQL / mysql - अलग / UNIQUE चुनें लेकिन सभी कॉलम लौटाएँ?


373
SELECT DISTINCT field1, field2, field3, ......   FROM table

मैं निम्नलिखित एसक्यूएल कथन को पूरा करने की कोशिश कर रहा हूं, लेकिन मैं चाहता हूं कि यह सभी कॉलमों को वापस कर सके? कुछ इस तरह:

SELECT DISTINCT field1, * from table

12
SELECT DISTINCT * FROM tableआपके लिए काम क्यों नहीं करता है?
ypercube y

19
यदि आपकी तालिका में PK है तो सभी पंक्तियाँ distinctपरिभाषा के अनुसार होनी चाहिए । यदि आप केवल चयन करने का प्रयास कर रहे हैं, DISTINCT field1लेकिन किसी भी तरह अन्य सभी कॉलम लौटाते हैं, तो उन स्तंभों के लिए क्या होना चाहिए जिनके पास किसी विशेष field1मान के लिए एक से अधिक मूल्य हैं? आपको GROUP BYउदाहरण के लिए अन्य स्तंभों पर कुछ प्रकार के एकत्रीकरण का उपयोग करने की आवश्यकता होगी ।
मार्टिन स्मिथ

1
यदि आप बार-बार पंक्तियाँ चाहते हैं और केवल अलग पंक्तियाँ नहीं हैं, तो अलग-अलग कुंजी शब्द हटा दें।
हाइपरबोरस

2
क्या आप इस बात का उदाहरण दे सकते हैं कि आप परिणामों की अपेक्षा क्या करते हैं? अब तक, मैं आपकी इच्छित क्वेरी का कोई मतलब नहीं निकाल सकता।
पुनरावर्ती

3
यहां पूछे गए समान प्रश्न का उत्तर है, आपको पहले उनकी आईडी के साथ अलग-अलग कॉलम प्राप्त करना होगा और फिर इसे मूल तालिका के साथ जोड़ना होगा। एक कॉलम पर DISTINCT का चयन करें, कई अन्य कॉलम
लौटाएँ

जवाबों:


407

आप इसके लिए एक समूह खोज रहे हैं:

select *
from table
group by field1

जिसे कभी-कभी स्टेटमेंट पर अलग से लिखा जा सकता है:

select distinct on field1 *
from table

अधिकांश प्लेटफार्मों पर, हालांकि, उपरोक्त में से कोई भी काम नहीं करेगा क्योंकि अन्य स्तंभों पर व्यवहार अनिर्दिष्ट है। (MySQL में पहला काम करता है, यदि आप इसका उपयोग कर रहे हैं।)

आप अलग-अलग फ़ील्ड ला सकते हैं और हर बार एकल मनमानी पंक्ति चुन सकते हैं।

कुछ प्लेटफ़ॉर्म पर (जैसे PostgreSQL, Oracle, T-SQL) इसे सीधे विंडो फ़ंक्शंस का उपयोग करके किया जा सकता है:

select *
from (
   select *,
          row_number() over (partition by field1 order by field2) as row_number
   from table
   ) as rows
where row_number = 1

दूसरों (MySQL, SQLite) पर, आपको उपश्रेणियों को लिखना होगा जो आपको पूरी तालिका को स्वयं ( उदाहरण ) के साथ जोड़ देगा , इसलिए अनुशंसित नहीं है।


10
क्वेरी मेरे लिए पार्स नहीं है और एक त्रुटि देता है: The ranking function "row_number" must have an ORDER BY clause। हमें फ़ील्ड 1 द्वारा विभाजन के बाद खंड द्वारा आदेश जोड़ना होगा। तो सही क्वेरी होगी select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
अंकुर-एम

1
धन्यवाद! मैं उसी समस्या में था और समाधान था GROUP BY
जोकिन इराचुक

2
इसके अलावा Oracle (Oracle SQL Developer) में आप निर्दिष्ट नहीं कर सकते select *, row_number() over (partition by field1 order by field2) as row_number from table। आपको स्पष्ट रूप से तालिका नाम / उपनाम का चयन क्वेरी में उपयोग करना होगाselect **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
meta4

1
@ कर्ल: आज ... हो सकता है। जैसा कि आप देख सकते हैं, यह उत्तर लगभग 7 साल पुराना है, समय का एक बिंदु जहां यह मामला नहीं था क्योंकि मैं सक्रिय होने पर वापस से याद कर सकता हूं। यदि आपको लगता है कि यह आवश्यक है, तो आप फिर से स्वागत और / या उत्तर को संपादित कर सकते हैं।
डेनिस डे बर्नार्डी

2
select distinct on (field1) * from table; PostgreSQL में भी काम करता है
चिलियानू बोगडान

61

आपके प्रश्न के वाक्यांशांकन से, मैं समझता हूं कि आप किसी दिए गए फ़ील्ड के लिए अलग-अलग मानों का चयन करना चाहते हैं और प्रत्येक ऐसे मान के लिए एक ही पंक्ति में अन्य सभी स्तंभ मानों को सूचीबद्ध करना चाहते हैं। अधिकांश DBMS इसे न तो DISTINCTऔर न ही अनुमति देंगे GROUP BY, क्योंकि परिणाम निर्धारित नहीं होता है।

इसे इस तरह से सोचें: यदि आपका field1एक से अधिक बार होता है, तो किस मूल्य को field2सूचीबद्ध किया जाएगा (यह देखते हुए कि आपके पास field1दो पंक्तियों में समान मूल्य है, लेकिन field2उन दो पंक्तियों में दो अलग-अलग मूल्य हैं)।

हालाँकि आप समग्र कार्यों का उपयोग कर सकते हैं (प्रत्येक क्षेत्र के लिए कुशलता से जिसे आप दिखाना चाहते हैं) और GROUP BYइसके बजाय का उपयोग कर रहे हैं DISTINCT:

SELECT field1, MAX(field2), COUNT(field3), SUM(field4), .... FROM table GROUP BY field1

4
इस समाधान के लिए +1। तो हम क्या कर सकते हैं SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1, और field2, 3, 4 ,,, पूर्णांकों (या अन्य अंक) होना आवश्यक नहीं कर रहे हैं, वे चार क्षेत्रों किया जा सकता है साथ ही साथ
डंठल

तब तक अच्छी तरह से काम कर रहा था जब तक कि मैं बूलियन कॉलम में फंस नहीं गया। MIN (डायनेमिक) कॉलम मान गलत होने पर भी संशोधित हो जाते हैं .. यह बूलियन को संबोधित करने के लिए उपलब्ध कोई भी अन्य कार्य है - हस्ताक्षरकर्ता 6 मिनट पहले। Sum (गतिशील) 1 से बदल गया
2

1
महान सुझाव, मुझे मेरे समाधान की ओर ले गया जो मुझे लगता है कि अधिक सार्वभौमिक है - एक नज़र डालें!
गैरेट सिम्पसन

@signonsridhar ने आपके बूलियन को एक इंट और उपयोग राशि में डाला; जैसेsum(cast(COL as int)) > 0
ड्रयू

26

अगर मैंने आपकी समस्या को सही ढंग से समझा, तो यह मेरे जैसा ही था। आप सभी डेटा पर लागू करने के बजाय DISTINCT की प्रयोज्य को एक निर्दिष्ट क्षेत्र में सीमित करना चाहते हैं।

यदि आप एक समग्र फ़ंक्शन के बिना ग्रुप BY का उपयोग करते हैं, तो कभी भी जो आप ग्रुप बीई करते हैं, वह आपका DISTINCT दायर होगा।

यदि आप अपना प्रश्न बनाते हैं:

SELECT * from table GROUP BY field1;

यह फ़ील्ड 1 के एकल उदाहरण के आधार पर आपके सभी परिणाम दिखाएगा।

उदाहरण के लिए, यदि आपके पास नाम, पता और शहर के साथ एक तालिका है। एक एकल व्यक्ति के कई पते दर्ज हैं, लेकिन आप केवल उस व्यक्ति के लिए एक ही पता चाहते हैं, आप निम्नानुसार क्वेरी कर सकते हैं:

SELECT * FROM persons GROUP BY name;

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

SELECT * FROM persons GROUP BY lastName, firstName;

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


जैसा कि स्वीकृत उत्तर में उल्लेख किया गया है, SQL के अधिकांश अवतारों के लिए काम करेगा - केवल MYSQL के लिए
गैरेट सिम्पसन

15
SELECT  c2.field1 ,
        field2
FROM    (SELECT DISTINCT
                field1
         FROM   dbo.TABLE AS C
        ) AS c1
        JOIN dbo.TABLE AS c2 ON c1.field1 = c2.field1

क्यों वहाँ है C aliasजब यह इसके बिना काम कर सकता है? पंक्ति मेंFROM dbo.TABLE AS C
तलहा

2
मेरा मानना ​​है कि यह RedGate SQLPrompt के मेरे उपयोग के कारण है। जिस तरह से मैंने इसे कॉन्फ़िगर किया है, यह हमेशा उपनाम जोड़ता है - भले ही अनावश्यक हो। यह "सिर्फ मामले में" है
स्टॉर्मी

यह मेरे लिए आशाजनक लग रहा था, लेकिन यह अभी भी सभी फ़ील्ड्स को वापस लाया है, विशेष फ़ील्ड 1 नहीं। :(
माइकल फीवर

13

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

जब तक आप अतिरिक्त जानकारी को क्वेरी नहीं करते, तब तक ग्रुप बाय स्टेटमेंट के साथ क्वेरी परिणामों की संख्या कम करना आसान होता है। मान लें कि आपको निम्न तालिका 'स्थान' मिल गए हैं।

--country-- --city--
 France      Lyon
 Poland      Krakow
 France      Paris
 France      Marseille
 Italy       Milano

अब सवाल है

SELECT country FROM locations
GROUP BY country

में परिणाम होगा:

--country--
 France
 Poland
 Italy

हालाँकि, निम्नलिखित क्वेरी

SELECT country, city FROM locations
GROUP BY country

... एमएस एसक्यूएल में एक त्रुटि फेंकता है, क्योंकि आपका कंप्यूटर कैसे जान सकता है कि तीन फ्रांसीसी शहरों "ल्योन", "पेरिस" या "मार्सिले" में से कौन सा क्षेत्र "फ्रांस" के दाईं ओर पढ़ना चाहते हैं?

दूसरी क्वेरी को सही करने के लिए, आपको इस जानकारी को जोड़ना होगा। ऐसा करने का एक तरीका सभी उम्मीदवारों में से सबसे बड़े या सबसे छोटे मूल्य का चयन करते हुए मैक्स () या MIN () फ़ंक्शन का उपयोग करना है। MAX () और MIN () न केवल संख्यात्मक मानों पर लागू होते हैं, बल्कि स्ट्रिंग मानों के वर्णमाला क्रम की भी तुलना करते हैं।

SELECT country, MAX(city) FROM locations
GROUP BY country

में परिणाम होगा:

--country-- --city--
 France      Paris
 Poland      Krakow
 Italy       Milano

या:

SELECT country, MIN(city) FROM locations
GROUP BY country

में परिणाम होगा:

--country-- --city--
 France      Lyon
 Poland      Krakow
 Italy       Milano

जब तक आप वर्णमाला (या संख्यात्मक) क्रम के दोनों सिरों से अपने मूल्य का चयन करने के साथ ठीक हैं तब तक ये फ़ंक्शन एक अच्छा समाधान हैं। लेकिन अगर यह मामला नहीं है तो क्या होगा? हमें मान लें कि आपको एक निश्चित विशेषता के साथ एक मूल्य की आवश्यकता है, उदाहरण के लिए 'एम' अक्षर से शुरू करना। अब चीजें जटिल हो गई हैं।

एकमात्र उपाय जो मैं अब तक पा सकता था, वह यह है कि आप अपनी पूरी क्वेरी को एक सबक्वेरी में डाल दें, और इसके द्वारा अतिरिक्त कॉलम का निर्माण करें:

SELECT
     countrylist.*,
     (SELECT TOP 1 city
     FROM locations
     WHERE
          country = countrylist.country
          AND city like 'M%'
     )
FROM
(SELECT country FROM locations
GROUP BY country) countrylist

में परिणाम होगा:

--country-- --city--
 France      Marseille
 Poland      NULL
 Italy       Milano

5

महान प्रश्न @aryaxt - आप बता सकते हैं कि यह एक महान प्रश्न था क्योंकि आपने इसे 5 साल पहले पूछा था और मैंने आज इस पर जवाब देने की कोशिश में ठोकर खाई!

मैंने इसे शामिल करने के लिए स्वीकृत उत्तर को संपादित करने का प्रयास किया, लेकिन यदि मेरा संपादन इसमें नहीं होता है:

यदि आपकी तालिका इतनी बड़ी नहीं थी, और अपनी प्राथमिक कुंजी मान लेना एक ऑटो-इंक्रीमेंटिंग पूर्णांक था, तो आप ऐसा कुछ कर सकते हैं:

SELECT 
  table.*
FROM table
--be able to take out dupes later
LEFT JOIN (
  SELECT field, MAX(id) as id
  FROM table
  GROUP BY field
) as noDupes on noDupes.id = table.id
WHERE
  //this will result in only the last instance being seen
  noDupes.id is not NULL


3

आप इसे एक WITHखंड के साथ कर सकते हैं ।

उदाहरण के लिए:

WITH c AS (SELECT DISTINCT a, b, c FROM tableName)
SELECT * FROM tableName r, c WHERE c.rowid=r.rowid AND c.a=r.a AND c.b=r.b AND c.c=r.c

इससे आप केवल WITHक्लॉस क्वेरी में चयनित पंक्तियों का चयन कर सकते हैं।


2

SQL सर्वर के लिए आप dense_rank और अतिरिक्त विंडोिंग फ़ंक्शंस का उपयोग कर निर्दिष्ट पंक्तियों पर डुप्लिकेट किए गए मानों के साथ सभी पंक्तियों और स्तंभों को प्राप्त कर सकते हैं। यहाँ एक उदाहरण है...

with t as (
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r1' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r2' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r3' union all
    select col1 = 'a', col2 = 'b', col3 = 'c', other = 'r4' union all
    select col1 = 'c', col2 = 'b', col3 = 'a', other = 'r5' union all
    select col1 = 'a', col2 = 'a', col3 = 'a', other = 'r6'
), tdr as (
    select 
        *, 
        total_dr_rows = count(*) over(partition by dr)
    from (
        select 
            *, 
            dr = dense_rank() over(order by col1, col2, col3),
            dr_rn = row_number() over(partition by col1, col2, col3 order by other)
        from 
            t
    ) x
)

select * from tdr where total_dr_rows > 1

यह col1, col2 और col3 के प्रत्येक अलग संयोजन के लिए एक पंक्ति गणना ले रहा है।


बहुत जटिल और SQL के एक कार्यान्वयन के लिए विशिष्ट
गैरेट सिम्पसन

1
select min(table.id), table.column1
from table 
group by table.column1

यह मेरे लिए काम किया !! यह ध्यान देने योग्य बात है, यदि आप fetch_array () का उपयोग कर रहे हैं, तो आपको प्रत्येक पंक्ति को अनुक्रमणिका लेबल के माध्यम से कॉल करने की आवश्यकता होगी बजाय इसके कि पंक्ति का नाम कहा जाए। मेरे लिए मेरे द्वारा दिए गए उदाहरण को लिखने के लिए इसमें पर्याप्त वर्ण नहीं हैं: एक्स सॉरी !!
ब्रैंडन प्रिंटिस

0
SELECT *
FROM tblname
GROUP BY duplicate_values
ORDER BY ex.VISITED_ON DESC
LIMIT 0 , 30

in ORDER BYमैंने अभी यहाँ उदाहरण दिया है, आप इसमें ID फ़ील्ड भी जोड़ सकते हैं


जैसा कि स्वीकृत उत्तर में बताया गया है, SQL के अधिकांश अवतारों के लिए काम करेगा - केवल MYSQL के लिए
गैरेट सिम्पसन

0

यहाँ कहीं और मिला, लेकिन यह एक सरल उपाय है जो काम करता है:

 WITH cte AS /* Declaring a new table named 'cte' to be a clone of your table */
 (SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val1 DESC) AS rn
 FROM MyTable /* Selecting only unique values based on the "id" field */
 )
 SELECT * /* Here you can specify several columns to retrieve */
 FROM cte
 WHERE rn = 1

MSSQL के लिए काम करता है
माइकल फीवर

-1

अपनी पसंद की क्वेरी देखने के लिए आप जिस फ़ील्ड को डुप्लिकेट करना चाहते हैं उसे फ़ील्ड में ग्रुप बी जोड़ें

SELECT field1, field2, field3, ......   FROM table GROUP BY field1

डुप्लिकेट रिकॉर्ड को बाहर करने के लिए फ़ील्ड 1 की जाँच की जाएगी

या आप की तरह क्वेरी कर सकते हैं

SELECT *  FROM table GROUP BY field1

फ़ील्ड 1 के डुप्लिकेट रिकॉर्ड को SELECT से बाहर रखा गया है


1
ग्रुप बाय क्लॉज चयनित क्षेत्रों से मेल खाना चाहिए। अन्यथा यह त्रुटि की तरह फेंक देगाfiled2 must appear in the GROUP BY clause or be used in an aggregate function
viuu -a

-2

बस अपने सभी फ़ील्डों को ग्रुप BY क्लॉज़ में शामिल करें।


3
इसे एक अच्छा जवाब बनाने के लिए, आपको अपने मतलब के बारे में थोड़ा और विस्तार करना चाहिए।
रोबर्ट

-2

यह आंतरिक क्वेरी द्वारा किया जा सकता है

$query = "SELECT * 
            FROM (SELECT field
                FROM table
                ORDER BY id DESC) as rows               
            GROUP BY field";

2
यह इस सवाल का जवाब नहीं देता है, ओपी तालिका के सभी आंकड़ों को प्राप्त करने की कोशिश कर रहा था, लेकिन एक ही क्षेत्र के डुप्लिकेट युक्त पंक्तियों को हटा दें
गैरेट सिम्पसन

-3
SELECT * from table where field in (SELECT distinct field from table)

7
वह काम नहीं करेगा। आपने उप-स्तंभ में अलग-अलग कॉलम का चयन किया है, लेकिन जहां क्लॉज को उस मान के साथ सभी कॉलम मिलते हैं। इसलिए क्वेरी 'तालिका से * का चयन करें' के रूप में अच्छा है जब तक कि 'फ़ील्ड' कॉलम एक अद्वितीय स्तंभ नहीं होता है, उस स्थिति में उस स्तंभ पर विशिष्ट की आवश्यकता नहीं होती है।
अंकुर-एम

-3

तालिका में सभी तीन स्तंभों के मान अनन्य हैं, तो DISTINCT FIELD1, FIELD2, FIELD3 FABLE TABLE1 काम करता है।

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


2
यह इस सवाल का जवाब नहीं देता है, ओपी तालिका के सभी आंकड़ों को प्राप्त करने की कोशिश कर रहा था लेकिन एक ही क्षेत्र के डुप्लिकेट युक्त पंक्तियों को हटा दें
गैरेट सिम्पसन

-3

मैं उपयोग करने का सुझाव दूंगा

SELECT  * from table where field1 in 
(
  select distinct field1 from table
)

इस तरह यदि आप कई पंक्तियों में फ़ील्ड 1 में समान मान रखते हैं, तो सभी रिकॉर्ड वापस आ जाएंगे।


1
यह अलग नहीं है SELECT * FROM table;। और भी यह धीमा है।
शिन किम

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