प्रत्येक समूह की पहली पंक्ति का चयन कैसे करें?


57

मेरे पास इस तरह की एक तालिका है:

 ID |  Val   |  Kind
----------------------
 1  |  1337  |   2
 2  |  1337  |   1
 3  |   3    |   4
 4  |   3    |   4

मैं एक बनाना चाहते SELECTहै कि प्रत्येक के लिए सिर्फ पहली पंक्ति वापस आ जाएगी Val, द्वारा आदेश देने Kind

नमूना उत्पादन:

 ID |  Val   |  Kind
----------------------
 2  |  1337  |   1
 3  |   3    |   4

मैं यह क्वेरी कैसे बना सकता हूं?


क्यों 3 | 3 | 4 और 4 नहीं | 3 | 4 - टाई-ब्रेक क्या है या आपको परवाह नहीं है?
जैक डगलस

@JackDouglas वास्तव में मेरे पास एक है ORDER BY ID DESC, लेकिन यह सवाल के लिए प्रासंगिक नहीं है। इस उदाहरण में मुझे कोई फर्क नहीं पड़ता।
ब्रूनोएलएम

जवाबों:


38

यह समाधान भी उपयोग करता है keep, लेकिन valऔर kindभी बस एक सबक्वेरी के बिना प्रत्येक समूह के लिए गणना की जा सकती:

select min(id) keep(dense_rank first order by kind) id
     , val
     , min(kind) kind
  from mytable
 group by val;
आईडी | वैल | मेहरबान
-: | ---: | ---:
 3 | 3 | 4
 2 | 1337 | 1

यहाँ dbfiddle

KEEP… FIRST और KEEP… LAST समुच्चय की एक Oracle-विशिष्ट विशेषता है - आप इसके बारे में यहाँ Oracle docs में, या ORACLE_BASE पर पढ़ सकते हैं :

FIRST और LAST फ़ंक्शंस का उपयोग ऑर्डर किए गए अनुक्रम से पहले या अंतिम मान को वापस करने के लिए किया जा सकता है


62

एक सामान्य टेबल एक्सप्रेशन (CTE) और एक विंडोिंग / रैंकिंग / पार्टीशन फ़ंक्शन जैसे ROW_NUMBER का उपयोग करें

यह क्वेरी ORDERED नामक एक इन-मेमोरी टेबल बनाएगी और rn का एक अतिरिक्त कॉलम जोड़ेगी जो 1 से N तक की संख्याओं का एक क्रम है। पार्टी द्वारा यह इंगित करता है कि इसे हर बार 1 पर फिर से शुरू होना चाहिए वैल वैल्यू में बदलाव और हम ऑर्डर करना चाहते हैं किंड के सबसे छोटे मूल्य द्वारा पंक्तियाँ।

WITH ORDERED AS
(
SELECT
    ID
,   Val
,   kind
,   ROW_NUMBER() OVER (PARTITION BY Val ORDER BY Kind ASC) AS rn
FROM
    mytable
)
SELECT
    ID
,   Val
,   Kind
FROM
    ORDERED
WHERE
    rn = 1;

उपरोक्त दृष्टिकोण किसी भी RDBMS के साथ काम करना चाहिए जिसने ROW_NUMBER () फ़ंक्शन को लागू किया है। ओरेकल की कुछ सुंदर कार्यक्षमता है जैसा कि माइक के उत्तर में व्यक्त किया गया है जो आम तौर पर इस उत्तर की तुलना में बेहतर प्रदर्शन करेगा।


25

बिलिंक का समाधान ठीक काम करता है, लेकिन मुझे लगा कि मैं भी अपना काम करूंगा। इसकी समान लागत है, लेकिन यह तेज़ हो सकता है (या धीमा, मैंने इसे परीक्षण नहीं किया है)। अंतर यह है कि यह Row_Number के बजाय First_Value का उपयोग करता है। चूंकि हम केवल पहले मूल्य में रुचि रखते हैं, मेरे दिमाग में यह अधिक सीधा है।

SELECT ID, Val, Kind FROM
(
   SELECT First_Value(ID) OVER (PARTITION BY Val ORDER BY Kind) First, ID, Val, Kind 
   FROM mytable
)
WHERE ID = First;

परीक्षण डेटा।

--drop table mytable;
create table mytable (ID Number(5) Primary Key, Val Number(5), Kind Number(5));

insert into mytable values (1,1337,2);
insert into mytable values (2,1337,1);
insert into mytable values (3,3,4);
insert into mytable values (4,3,4);

यदि आप पसंद करते हैं, तो यहां सीटीई समकक्ष है।

WITH FirstIDentified AS (
   SELECT First_Value(ID) OVER (PARTITION BY Val ORDER BY Kind) First, ID, Val, Kind 
   FROM mytable
   )
SELECT ID, Val, Kind FROM FirstIdentified
WHERE ID = First;

1
+1 लेकिन मैंने केवल इस बात पर जोर देने के लायक समझा कि आपका जवाब और बिलिंक तार्किक रूप से समान नहीं हैं जब तक idकि अद्वितीय न हो।
जैक डगलस

@ जेक डगलस - सच है, मैंने मान लिया।
लीघ रिफ़ेल

14

आप प्रत्येक समूह से keepचयन करने के लिए उपयोग कर सकते हैं id:

select *
from mytable
where id in ( select min(id) keep (dense_rank first order by kind, id)
              from mytable
              group by val );
आईडी | वैल | मेहरबान
-: | ---: | ---:
 2 | 1337 | 1
 3 | 3 | 4

यहाँ dbfiddle


2
SELECT MIN(MyTable01.Id) as Id,
       MyTable01.Val     as Val,
       MyTable01.Kind    as Kind 
  FROM MyTable MyTable01,                         
       (SELECT Val,MIN(Kind) as Kind
          FROM MyTable                   
      GROUP BY Val) MyTableGroup
WHERE MyTable01.Val  = MyTableGroup.Val
  AND MyTable01.Kind = MyTableGroup.Kind
GROUP BY MyTable01.Val,MyTable01.Kind
ORDER BY Id;

यह इस तथ्य के कारण अन्य उत्तरों की तुलना में बहुत कम कुशल होगा कि MyTable पर दो स्कैन की आवश्यकता है।
a_horse_with_no_name

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