2011-02-04 84 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' 
相关问题