2011-02-04 11 views
11

मैं SQL सर्वर 2005 का उपयोग कर रहा हूं। मेरे पास भुगतान आईडी, उपयोगकर्ता आईडी और टाइमस्टैम्प के साथ एक भुगतान तालिका है। मैं प्रत्येक उपयोगकर्ता के लिए सबसे हालिया भुगतान खोजना चाहता हूं। यह खोजना आसान है और इसका उत्तर ढूंढना आसान है। मैं यह भी जानना चाहता हूं कि सबसे हालिया भुगतान उपयोगकर्ता का पहला भुगतान है या नहीं।SQL सर्वर में प्रति समूह/विभाजन अधिकतम पंक्ति संख्या कैसे प्राप्त करें?

SELECT 
    p.payment_id, 
    p.user_id, 
    ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date) AS paymentNumber 
FROM 
    payment p 

मैं मानसिक छलांग जो तब की सुविधा देता है मुझे तो प्रति उपयोगकर्ता उच्चतम PaymentNumber लेने नहीं बना रहा हूं:

मैं जिसके बाद प्रत्येक उपयोगकर्ता के भुगतान नंबर होगा। यदि मैं उपरोक्त का उपयोग MAX (PaymentNumber) का उपयोग कर उप-चयन के रूप में करता हूं और फिर user_id द्वारा समूहित करता हूं, तो मुझे भुगतान_आईडी खो देता है जो मुझे चाहिए। लेकिन अगर मैं क्लॉज द्वारा समूह में payment_id भी जोड़ता हूं, तो मैं प्रति भुगतान एक पंक्ति पर वापस आ जाता हूं। मुझे यकीन है कि मैं स्पष्ट दिख रहा हूं। कोई मदद?

+0

वहाँ सब पर मेज पर एक प्राथमिक कुंजी है? – DForck42

+0

प्राथमिक कुंजी payment_id है। – DaveBurns

उत्तर

25

इस प्रयास करें:

SELECT a.*, CASE WHEN totalPayments>1 THEN 'NO' ELSE 'YES' END IsFirstPayment 
    FROM(
       SELECT p.payment_id,  
           p.user_id,  
           ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date DESC) AS paymentNumber, 
           SUM(1) OVER (PARTITION BY p.user_id) AS totalPayments 
        FROM payment p 
      ) a 
WHERE paymentNumber = 1  
+1

'COUNT (*)' होने पर SUM (1) का उपयोग क्यों करें ?? – RichardTheKiwi

+0

क्यों नहीं? क्या कोई प्रदर्शन मुद्दा है? – Chandu

+1

'गणना (*)' तेज होगी, आंत महसूस होगा। इसे रिकॉर्ड की जांच करने की भी आवश्यकता नहीं है, केवल सूचकांक लंबाई। योग (1) को प्रत्येक पंक्ति के लिए मान 1 बनाना है और इसे टैली करना है। आप आम तौर पर रिकॉर्ड की गणना करने के लिए 'tbl' से' चयनित योग (1) लिखना नहीं चाहते हैं? – RichardTheKiwi

2
; with cte as (
SELECT 
    p.payment_id, 
    p.user_id, 
    ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date desc) AS paymentNumber 
FROM 
    payment p 
) select * from cte where paymentNumber = 1 
10

फिर से एक ही बात करते हैं।

SELECT 
    p.payment_id, 
    p.user_id, 
    ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date) AS paymentNumber, 
    ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date DESC) AS reversePaymentNumber, 
FROM 
    payment p 

अब हालिया भुगतान में रिवर्सपेमेंट नंबर 1 है, और भुगतान की संख्या भुगतान संख्या होगी।

+1

आपके उत्तर ने मुझे विभाजन में 1 से अधिक पंक्तियों के साथ पंक्तियों के समूह का चयन करने में मदद की। मैंने पंक्ति संख्या और रिवर्स पंक्ति संख्या और चयनित पंक्तियों को सारांशित किया जहां योग 2 से अधिक था। धन्यवाद! –

0

इस बारे में कैसे?

SELECT 
    p.user_id, 
    MAX(p.payment_date) as lastPayment, 
    CASE COUNT(p.payment_id) WHEN 1 THEN 1 ELSE 0 END as isFirstPayment 
FROM 
    payment p 
GROUP BY 
    p.user_id 
+1

एसक्यूएल सर्वर में बुलियन डेटाटाइप 'COUNT (p.payment_id) = 1' को 'केस' अभिव्यक्ति होने की आवश्यकता नहीं होगी। –

+0

इसके अलावा, मुझे output_id को आउटपुट के रूप में चाहिए। जैसा कि मैंने मूल प्रश्न में कहा था, यदि आप इसे आउटपुट और समूह में क्लॉज द्वारा डालते हैं, तो आप केवल नवीनतम भुगतान के लिए प्रत्येक भुगतान के लिए एक पंक्ति प्राप्त करते हैं। – DaveBurns

0

एक कम अच्छा तरीका मैं लगता

; with maxp as 
(
    select 
     p.user_id, 
     max(p.payment_date) as MaxPaymentDate 
    from payment p 
    group by p.userid 
), 
nump as 
(
    select 
     p.payment_id,  
     p.user_id,  
     p.payment_date, 
     ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.payment_date) AS paymentNumber 
    FROM payment p 
), 
a as 
(
select 
    nump.payment_id, 
    nump.user_id, 
    nump.paymentNumber 
    case when maxp.MaxPaymentDate is null then 'Old' else 'New' end as NewState 
from nump 
    left outer join maxp 
     on nump.user_id=maxp.user_id 
      and nump.payment_date=maxp.MaxPaymentDate 
) 

select 
* 
from a 
where NewState='New' 
संबंधित मुद्दे