sql - उस पंक्ति को प्राप्त करें जिसमें कॉलम के लिए अधिकतम मान है




oracle greatest-n-per-group (20)

(टी-एसक्यूएल) पहले सभी उपयोगकर्ताओं और उनके maxdate प्राप्त करें। Maxdates पर उपयोगकर्ताओं के लिए संबंधित मान खोजने के लिए तालिका के साथ जुड़ें।

create table users (userid int , value int , date datetime)
insert into users values (1, 1, '20010101')
insert into users values (1, 2, '20020101')
insert into users values (2, 1, '20010101')
insert into users values (2, 3, '20030101')

select T1.userid, T1.value, T1.date 
    from users T1,
    (select max(date) as maxdate, userid from users group by userid) T2    
    where T1.userid= T2.userid and T1.date = T2.maxdate

परिणाम:

userid      value       date                                    
----------- ----------- -------------------------- 
2           3           2003-01-01 00:00:00.000
1           2           2002-01-01 00:00:00.000

तालिका:

UserId, Value, Date.

मैं UserId प्राप्त करना चाहता हूं, प्रत्येक उपयोगकर्ता आईडी के लिए अधिकतम (दिनांक) के लिए मान। यही है, प्रत्येक उपयोगकर्ता आईडी के लिए मूल्य जिसमें नवीनतम तिथि है। एसक्यूएल में ऐसा करने का कोई तरीका है? (पसंदीदा ओरेकल)

अद्यतन: किसी भी अस्पष्टता के लिए माफ़ी: मुझे सभी उपयोगकर्ता आईडी प्राप्त करने की आवश्यकता है। लेकिन प्रत्येक UserId के लिए, केवल वह पंक्ति जहां उस उपयोगकर्ता की नवीनतम तिथि है।


MySQL के लिए समाधान जिसमें विभाजन KEPP, DENSE_RANK की अवधारणा नहीं है।

select userid,
       my_date,
       ...
from
(
select @sno:= case when @pid<>userid then 0
                    else @sno+1
    end as serialnumber, 
    @pid:=userid,
       my_Date,
       ...
from   users order by userid, my_date
) a
where a.serialnumber=0

संदर्भ: http://benincampus.blogspot.com/2013/08/select-rows-which-have-maxmin-value-in.html


एक गुणवत्ता खंड दोनों सरल और सबसे अच्छा नहीं होगा?

select userid, my_date, ...
from users
qualify rank() over (partition by userid order by my_date desc) = 1

संदर्भ के लिए, टेराडाटा पर इस योग्य संस्करण के साथ 17 के दशक में और इनलाइनों के साथ इनलाइन का एक सभ्य आकार परीक्षण 'इनलाइन व्यू' / एल्ड्रिज समाधान # 1 के साथ है।


काम पर नहीं, मेरे पास ओरेकल हाथ नहीं है, लेकिन मुझे याद है कि ओरेकल एक कॉल में कई कॉलम मिलान करने की इजाजत देता है, जो कम से कम एक सहसंबंधित सबक्वायरी का उपयोग करने वाले विकल्पों से बचना चाहिए, जो शायद ही कभी अच्छा है विचार।

ऐसा कुछ, शायद (याद नहीं है कि कॉलम सूची को संश्लेषित किया जाना चाहिए या नहीं):

SELECT * 
FROM MyTable
WHERE (User, Date) IN
  ( SELECT User, MAX(Date) FROM MyTable GROUP BY User)

संपादित करें: बस इसे वास्तविक के लिए आजमाया:

SQL> create table MyTable (usr char(1), dt date);
SQL> insert into mytable values ('A','01-JAN-2009');
SQL> insert into mytable values ('B','01-JAN-2009');
SQL> insert into mytable values ('A', '31-DEC-2008');
SQL> insert into mytable values ('B', '31-DEC-2008');
SQL> select usr, dt from mytable
  2  where (usr, dt) in 
  3  ( select usr, max(dt) from mytable group by usr)
  4  /

U DT
- ---------
A 01-JAN-09
B 01-JAN-09

तो यह काम करता है, हालांकि कुछ अन्य भयानक सामानों का उल्लेख कहीं और अधिक प्रदर्शनशील हो सकता है।


बस काम पर एक "लाइव" उदाहरण लिखना पड़ा :)

यह एक ही तारीख पर UserId के लिए एकाधिक मानों का समर्थन करता है।

कॉलम: उपयोगकर्ता आईडी, मूल्य, तिथि

SELECT
   DISTINCT UserId,
   MAX(Date) OVER (PARTITION BY UserId ORDER BY Date DESC),
   MAX(Values) OVER (PARTITION BY UserId ORDER BY Date DESC)
FROM
(
   SELECT UserId, Date, SUM(Value) As Values
   FROM <<table_name>>
   GROUP BY UserId, Date
)

आप MAX के बजाय FIRST_VALUE का उपयोग कर सकते हैं और समझाए गए योजना में इसे देख सकते हैं। मेरे पास इसके साथ खेलने का समय नहीं था।

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


माना जाता है कि किसी दिए गए उपयोगकर्ता आईडी के लिए तिथि अद्वितीय है, यहां कुछ TSQL है:

SELECT 
    UserTest.UserID, UserTest.Value
FROM UserTest
INNER JOIN
(
    SELECT UserID, MAX(Date) MaxDate
    FROM UserTest
    GROUP BY UserID
) Dates
ON UserTest.UserID = Dates.UserID
AND UserTest.Date = Dates.MaxDate 

मुझे पता है कि आपने ओरेकल से पूछा, लेकिन एसक्यूएल 2005 में अब हम इसका इस्तेमाल करते हैं:


-- Single Value
;WITH ByDate
AS (
SELECT UserId, Value, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) RowNum
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE RowNum = 1

-- Multiple values where dates match
;WITH ByDate
AS (
SELECT UserId, Value, RANK() OVER (PARTITION BY UserId ORDER BY Date DESC) Rnk
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE Rnk = 1

मुझे लगता है कि कई लोग उप-सामान या अन्य विक्रेता-विशिष्ट विशेषताओं का उपयोग करते हैं, लेकिन मैं अक्सर निम्न प्रकार के उप-सामानों के बिना इस प्रकार की क्वेरी करता हूं। यह सादे, मानक एसक्यूएल का उपयोग करता है, इसलिए इसे आरडीबीएमएस के किसी भी ब्रांड में काम करना चाहिए।

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;

दूसरे शब्दों में: पंक्ति को टी 1 से प्राप्त करें जहां एक ही उपयोगकर्ता आईडी के साथ कोई अन्य पंक्ति मौजूद नहीं है और एक बड़ी तिथि है।

(मैंने पहचानकर्ताओं में पहचानकर्ता "दिनांक" रखा क्योंकि यह एक एसक्यूएल आरक्षित शब्द है।)

अगर t1."Date" = t2."Date" , दोगुना प्रतीत होता है। आमतौर पर टेबल में auto_inc(seq) कुंजी होती है, उदाहरण के लिए id । दोगुनी से बचने के लिए निम्नानुसार उपयोग किया जा सकता है:

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") 
         OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;

@ फ़ारहान से टिप्पणी करें:

यहां एक और विस्तृत स्पष्टीकरण दिया गया है:

एक बाहरी शामिल टी 2 के साथ टी 1 में शामिल होने का प्रयास करता है। डिफ़ॉल्ट रूप से, टी 1 के सभी परिणाम लौटाए जाते हैं, और यदि टी 2 में कोई मिलान होता है, तो यह भी वापस आ जाता है। यदि टी 1 की किसी दिए गए पंक्ति के लिए टी 2 में कोई मिलान नहीं है, तो क्वेरी अभी भी टी 1 की पंक्ति लौटाती है, और सभी टी 2 के कॉलम के लिए प्लेसहोल्डर के रूप में NULL का उपयोग करती है। यह सामान्य रूप से बाहरी रूप से कैसे काम करता है।

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

उन मामलों में (जब कोई मिलान नहीं होता है), टी 2 के कॉलम न्यूल होंगे - यहां तक ​​कि शामिल स्थिति में निर्दिष्ट कॉलम भी होंगे। इसलिए हम WHERE t2.UserId IS NULL उपयोग करते हैं, क्योंकि हम उन मामलों की खोज कर रहे हैं जहां दिए गए उपयोगकर्ता आईडी के लिए अधिक तिथि के साथ कोई पंक्ति नहीं मिली थी।


मेरे पास ओरेकल का परीक्षण करने के लिए नहीं है, लेकिन सबसे कुशल समाधान विश्लेषणात्मक प्रश्नों का उपयोग करना है। यह कुछ इस तरह दिखना चाहिए:

SELECT DISTINCT
    UserId
  , MaxValue
FROM (
    SELECT UserId
      , FIRST (Value) Over (
          PARTITION BY UserId
          ORDER BY Date DESC
        ) MaxValue
    FROM SomeTable
  )

मुझे संदेह है कि आप बाहरी क्वेरी से छुटकारा पा सकते हैं और आंतरिक पर अलग रख सकते हैं, लेकिन मुझे यकीन नहीं है। इस बीच में मैं यह जानता हूं कि यह एक काम करता है।

यदि आप विश्लेषणात्मक प्रश्नों के बारे में जानना चाहते हैं, तो मैं http://www.orafaq.com/node/55 और http://www.akadia.com/services/ora_analytic_functions.html पढ़ने का सुझाव दूंगा। संक्षिप्त सारांश यहां दिया गया है।

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

इस मामले में आंतरिक क्वेरी क्या करती है। पूरे डेटासेट को UserId द्वारा दिनांकित दिनांक डीईएससी द्वारा क्रमबद्ध किया जाता है। फिर यह इसे एक पास में संसाधित करता है। प्रत्येक पंक्ति के लिए आप UserId और उस UserId के लिए पहली तारीख को वापस लौटाते हैं (चूंकि तिथियां डीईएससी को क्रमबद्ध की जाती हैं, यह अधिकतम तिथि है)। यह आपको डुप्लिकेट पंक्तियों के साथ आपका उत्तर देता है। फिर बाहरी DISTINCT डुप्लिकेट squashes।

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


मैं आपके सटीक कॉलम नाम नहीं जानता, लेकिन यह ऐसा कुछ होगा:

    select userid, value
      from users u1
     where date = (select max(date)
                     from users u2
                    where u1.userid = u2.userid)

मैं पार्टी के लिए काफी देर हो चुकी हूं लेकिन निम्नलिखित हैक दोनों सहसंबंधित सबक्वायरीज़ और किसी भी एनालिटिक्स फ़ंक्शन से बेहतर प्रदर्शन करेगा लेकिन एक प्रतिबंध है: मान स्ट्रिंग में परिवर्तित होना चाहिए। तो यह तिथियों, संख्याओं और अन्य तारों के लिए काम करता है। कोड अच्छा नहीं लग रहा है लेकिन निष्पादन प्रोफ़ाइल बहुत अच्छी है।

select
    userid,
    to_number(substr(max(to_char(date,'yyyymmdd') || to_char(value)), 9)) as value,
    max(date) as date
from 
    users
group by
    userid

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


यदि (उपयोगकर्ता आईडी, दिनांक) अद्वितीय है, यानी एक ही उपयोगकर्ता के लिए दो बार कोई तारीख दिखाई नहीं देती है तो:

select TheTable.UserID, TheTable.Value
from TheTable inner join (select UserID, max([Date]) MaxDate
                          from TheTable
                          group by UserID) UserMaxDate
     on TheTable.UserID = UserMaxDate.UserID
        TheTable.[Date] = UserMaxDate.MaxDate;

यदि आपके प्रश्न उस पृष्ठ के समान दिखते हैं तो यह लिंक देखें, तो मैं आपको निम्न प्रश्न का सुझाव दूंगा जो उस लिंक का समाधान देगा

select distinct sno,item_name,max(start_date) over(partition by sno),max(end_date) over(partition by sno),max(creation_date) over(partition by sno), max(last_modified_date) over(partition by sno) from uniq_select_records order by sno,item_name asc;

उस लिंक से संबंधित सटीक परिणाम दिए जाएंगे


यह उतना आसान होना चाहिए जितना:

SELECT UserId, Value
FROM Users u
WHERE Date = (SELECT MAX(Date) FROM Users WHERE UserID = u.UserID)

यह डुप्लिकेट का भी ख्याल रखेगा (प्रत्येक user_id के लिए एक पंक्ति लौटाएं):

SELECT *
FROM (
  SELECT u.*, FIRST_VALUE(u.rowid) OVER(PARTITION BY u.user_id ORDER BY u.date DESC) AS last_rowid
  FROM users u
) u2
WHERE u2.rowid = u2.last_rowid

यहां जवाब केवल ओरेकल है। यहां सभी एसक्यूएल में थोड़ा अधिक परिष्कृत उत्तर दिया गया है:

सर्वश्रेष्ठ समग्र होमवर्क परिणाम (होमवर्क पॉइंट का अधिकतम योग) कौन है?

SELECT FIRST, LAST, SUM(POINTS) AS TOTAL
FROM STUDENTS S, RESULTS R
WHERE S.SID = R.SID AND R.CAT = 'H'
GROUP BY S.SID, FIRST, LAST
HAVING SUM(POINTS) >= ALL (SELECT SUM (POINTS)
FROM RESULTS
WHERE CAT = 'H'
GROUP BY SID)

और एक और कठिन उदाहरण, जिसे कुछ स्पष्टीकरण की आवश्यकता है, जिसके लिए मेरे पास समय नहीं है:

पुस्तक (आईएसबीएन और शीर्षक) दें जो 2008 में सबसे लोकप्रिय है, यानि, जिसे 2008 में सबसे ज्यादा उधार लिया जाता है।

SELECT X.ISBN, X.title, X.loans
FROM (SELECT Book.ISBN, Book.title, count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title) X
HAVING loans >= ALL (SELECT count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title);

उम्मीद है कि यह मदद करता है (किसी भी) .. :)

विनम्र, गुस


Oracle 12c+ , आप विश्लेषणात्मक फ़ंक्शन rank के साथ शीर्ष एन प्रश्नों का उपयोग कर सकते हैं ताकि यह सबकुछ बिना संक्षेप में प्राप्त किया जा सके:

select *
from your_table
order by rank() over (partition by user_id order by my_date desc)
fetch first 1 row with ties;

उपरोक्त अधिकतम my_date प्रति उपयोगकर्ता के साथ सभी पंक्तियां लौटाती हैं।

यदि आप अधिकतम तिथि के साथ केवल एक पंक्ति चाहते हैं, तो rank को row_number साथ row_number :

select *
from your_table
order by row_number() over (partition by user_id order by my_date desc)
fetch first 1 row with ties; 

SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
  FROM table
  GROUP BY userid

select   UserId,max(Date) over (partition by UserId) value from users;

select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))





greatest-n-per-group