2011-02-04 85 views
11

我正在使用SQL Server 2005.我有付款ID,用戶ID和時間戳的付款表。我想爲每個用戶查找最新的付款。這很容易搜索並找到答案。但是,我也想知道的是,如果最近的付款是用戶的第一次付款或不是。如何獲取SQL Server中每個組/分區的最大行數?

我有人數將達到每個用戶的支付如下:

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 

,我不是做心理的飛躍,然後讓我,然後挑選每用戶最高的付款號。如果我通過使用MAX(paymentNumber)並使用user_id進行分組來使用上面的子查詢,我將失去我需要的payment_id。但是,如果我還將payment_id添加到group by子句中,那麼每回付款就回到一行。我確定我忽視了這個顯而易見的事實。任何幫助?

+0

有桌子上所有的主鍵? – DForck42 2011-02-04 22:25:16

+0

主鍵是payment_id。 – DaveBurns 2011-02-04 22:39:01

回答

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

爲什麼使用SUM(1)時有`COUNT(*)`? – RichardTheKiwi 2011-02-04 23:26:53

+0

爲什麼不呢?是否有任何性能問題? – Chandu 2011-02-04 23:29:01

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 

現在最近一次付款有reversePaymentNumber 1,付款次數爲paymentNumber。

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 
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' 
相關問題