SQL सर्वर: केवल MAX (DATE) वाली पंक्तियों का चयन करें


109

मेरे पास डेटा की एक तालिका है (db MSSQL है):

    ID  OrderNO PartCode  Quantity DateEntered
    417 2144     44917    100      18-08-11
    418 7235     11762    5        18-08-11
    419 9999     60657    100      18-08-11
    420 9999     60657    90       19-08-11

मैं एक क्वेरी बनाना चाहता हूं जो ऑर्डरनो, पार्टकोड और क्वांटिटी लौटाता है, लेकिन केवल अंतिम पंजीकृत ऑर्डर के लिए।

उदाहरण तालिका से मैं निम्नलिखित जानकारी प्राप्त करना चाहूंगा:

     OrderNO PartCode  Quantity     
     2144     44917    100      
     7235     11762    5        
     9999     60657    90      

ध्यान दें कि केवल एक लाइन 9999 ऑर्डर के लिए लौटा दी गई थी।

धन्यवाद!


2
अपनी टिप्पणी से, ROW_NUMBER () उत्तर के साथ जाएं। यह लंबे समय तक लग सकता है, लेकिन यह मेरे अनुभव में, उपयुक्त अनुक्रमित के साथ सबसे तेज़ है।
MatBailie

धन्यवाद Dems, मैं आपके प्रयास की सराहना करता हूं।
GEMI

1
@ जिमी सिर्फ जिज्ञासा से बाहर है, MAX(DATE)ऑर्डर 9999 के लिए एक लाइन नहीं लौटाता है?
ज़मीर

हां, लेकिन मैं चाहता था कि प्रत्येक अलग ऑर्डर केवल अंतिम ऑर्डर लाइन वापस करे।
GEMI

जवाबों:


184

अगर rownumber() over(...)आपके लिए उपलब्ध है…।

select OrderNO,
       PartCode,
       Quantity
from (select OrderNO,
             PartCode,
             Quantity,
             row_number() over(partition by OrderNO order by DateEntered desc) as rn
      from YourTable) as T
where rn = 1      

2
धन्यवाद मिकेल एरिकसन, यह एक भयानक क्वेरी है!
GEMI

56

सबसे अच्छा तरीका Mikael Eriksson है, अगर ROW_NUMBER()आप के लिए उपलब्ध है।

अगले सबसे अच्छा एक प्रश्न पर शामिल होने के लिए, Cularis के उत्तर के अनुसार है।

वैकल्पिक रूप से, सबसे सरल और सीधे आगे का रास्ता WHERE क्लॉज में एक सह-संबद्ध-उप-क्वेरी है।

SELECT
  *
FROM
  yourTable AS [data]
WHERE
  DateEntered = (SELECT MAX(DateEntered) FROM yourTable WHERE orderNo = [data].orderNo)

या ...

WHERE
  ID = (SELECT TOP 1 ID FROM yourTable WHERE orderNo = [data].orderNo ORDER BY DateEntered DESC)

29
select OrderNo,PartCode,Quantity
from dbo.Test t1
WHERE EXISTS(SELECT 1
         FROM dbo.Test t2
         WHERE t2.OrderNo = t1.OrderNo
           AND t2.PartCode = t1.PartCode
         GROUP BY t2.OrderNo,
                  t2.PartCode
         HAVING t1.DateEntered = MAX(t2.DateEntered))

यह ऊपर दिए गए सभी प्रश्नों का सबसे तेज़ है। क्वेरी की लागत 0.0070668 पर आई।

Mikael Eriksson द्वारा उपर्युक्त पसंदीदा उत्तर, 0.0146625 की क्वेरी लागत है

आप इस तरह के एक छोटे से नमूने के प्रदर्शन के बारे में परवाह नहीं कर सकते हैं, लेकिन बड़े प्रश्नों में, यह सब जोड़ता है।


2
यह मेरे लिए अन्य समाधानों की तुलना में ~ 3.5M पंक्ति डेटासेट पर मामूली तेजी से निकला, हालांकि SSMS ने एक सूचकांक का सुझाव दिया जो निष्पादन के समय को आधा कर देता है। धन्यवाद!
सहजना

तेज और सीधा। धन्यवाद।
स्टीफन ज़ेंग

मेरे पास 100k पंक्तियां हैं और मेरे लिए Mikael Eriksson की क्वेरी 3 गुना तेज है। हो सकता है कि यह इसलिए है क्योंकि मेरे पास खंड द्वारा विभाजन में समारोह है।
वचबर्न

यदि आपके पास 2 भिन्न आईडी के लिए समान मान (04/15/2017) के साथ दिनांक फ़ील्ड है, तो यह 2 पंक्तियाँ
लौटाएगा

हाँ पोर्टेकोई, यह सच है, लेकिन बिना किसी अन्य तरीके के दो पंक्तियों को अलग करने के लिए, आप एक दूसरे पर कैसे चयन कर सकते हैं? आप परिणाम पर एक शीर्ष डाल सकते हैं, लेकिन आप कैसे जानते हैं कि इसकी दूसरी पंक्ति नहीं है जो आप चाहते हैं?
टोन

10
SELECT t1.OrderNo, t1.PartCode, t1.Quantity
FROM table AS t1
INNER JOIN (SELECT OrderNo, MAX(DateEntered) AS MaxDate
            FROM table
            GROUP BY OrderNo) AS t2
ON (t1.OrderNo = t2.OrderNo AND t1.DateEntered = t2.MaxDate)

आंतरिक क्वेरी OrderNoअपनी अधिकतम तिथि के साथ सभी का चयन करती है । तालिका के अन्य स्तंभों को प्राप्त करने के लिए, आप उन पर OrderNoऔर से जुड़ सकते हैं MaxDate


1

MySql के लिए आप निम्नलिखित की तरह कुछ कर सकते हैं:

select OrderNO, PartCode, Quantity from table a
join (select ID, MAX(DateEntered) from table group by OrderNO) b on a.ID = b.ID

यदि आप ऑर्डर नंबर
जैकब

@Dems धन्यवाद @ cularis हाँ, यह MySql की बात कर रहा है, प्रश्न में निर्दिष्ट नहीं है कि डेटाबेस इंजन क्या है
bencobb

यदि आप कोड, XML या डेटा नमूने पोस्ट करते हैं, तो कृपया टेक्स्ट एडिटर में उन पंक्तियों को हाइलाइट करें और { }संपादक टूलबार पर "कोड सैंपल" बटन ( ) पर क्लिक करके अच्छी तरह से फॉर्मेट करें और सिंटैक्स इसे हाइलाइट करें!
marc_s

यह MSSQL है, इसके लिए क्षमा करें।
GEMI

1

और यू उस चुनिंदा स्टेटमेंट का भी उपयोग कर सकते हैं जैसे कि लेफ्ट जॉइन क्वेरी ... उदाहरण:

... left join (select OrderNO,
   PartCode,
   Quantity from (select OrderNO,
         PartCode,
         Quantity,
         row_number() over(partition by OrderNO order by DateEntered desc) as rn
  from YourTable) as T where rn = 1 ) RESULT on ....

आशा है कि यह मदद किसी को है कि इस के लिए खोज :)


1

rownumber () over (...) काम कर रहा है लेकिन मुझे 2 कारणों से यह समाधान पसंद नहीं आया। - यह फ़ंक्शन उपलब्ध नहीं है जब आप SQL2000 के पुराने संस्करण जैसे SQL2000 का उपयोग करते हैं - फ़ंक्शन पर निर्भरता और वास्तव में पठनीय नहीं है।

एक और उपाय है:

SELECT tmpall.[OrderNO] ,
       tmpall.[PartCode] ,
       tmpall.[Quantity] ,
FROM   (SELECT [OrderNO],
               [PartCode],
               [Quantity],
               [DateEntered]
        FROM   you_table) AS tmpall
       INNER JOIN (SELECT [OrderNO],
                          Max([DateEntered]) AS _max_date
                   FROM   your_table
                   GROUP  BY OrderNO ) AS tmplast
               ON tmpall.[OrderNO] = tmplast.[OrderNO]
                  AND tmpall.[DateEntered] = tmplast._max_date

1

अगर आपने आईडी और ऑर्डरऑन को अनुक्रमित किया है, तो आप IN का उपयोग कर सकते हैं: (मैं अस्पष्टता के लिए व्यापार सादगी से नफरत करता हूं, बस कुछ चक्रों को बचाने के लिए):

select * from myTab where ID in(select max(ID) from myTab group by OrderNo);

0

JOIN के उपयोग से बचने की कोशिश करें

SELECT SQL_CALC_FOUND_ROWS *  FROM (SELECT  msisdn, callid, Change_color, play_file_name, date_played FROM insert_log
   WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
 ORDER BY callid ASC) t1 JOIN (SELECT MAX(date_played) AS date_played FROM insert_log GROUP BY callid) t2 ON t1.date_played=t2.date_played

1
IN में क्यों बचें? क्या आपकी राय का समर्थन करने के लिए आपके पास कोई तर्क है?
प्रीज़ा

आपकी क्वेरी को निष्पादित करने में लंबा समय लगेगा। आप निम्नलिखित लेख xaprb.com/blog/2006/06/28/why-large-in-clauses-are-problematic
राजा नव

@anik यह 2006 का एक लेख है। क्या आपके पास इस बात का कोई प्रमाण है कि आप क्या कह रहे हैं?
फेलिक्स गगनोन-ग्रेनियर

0

यह मेरे लिए पूरी तरह से ठीक है।

    select name, orderno from (
         select name, orderno, row_number() over(partition by 
           orderno order by created_date desc) as rn from orders
    ) O where rn =1;

-1

यह मेरे लिए काम करता है। उपयोग मैक्स (CONVERT (तिथि, ReportDate)) सुनिश्चित करें कि आप दिनांक मान है बनाने के लिए

select max( CONVERT(date, ReportDate)) FROM [TraxHistory]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.