Как получить максимальный номер строки на группу/раздел в SQL Server?
Я использую SQL Server 2005. У меня есть таблица платежей с идентификаторами платежа, идентификаторами пользователя и отметками времени. Я хочу найти самую последнюю оплату для каждого пользователя. Это легко найти и найти ответ. Однако я также хочу знать, является ли последний платеж первым платежом пользователя или нет.
У меня есть следующее, которое будет указывать каждый пользовательский платеж:
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 (номер платежа), а затем группируя по user_id, я теряю нужный мне payment_id. Но если я также добавлю payment_id в предложение group by, я вернусь к одной строке за платеж. Я уверен, что я упускаю из виду очевидное. Любая помощь?
Ответы
Ответ 1
Попробуйте следующее:
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
Ответ 2
Повторите то же самое.
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, а количество платежей будет равно количеству платежей.
Ответ 3
; 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
Ответ 4
Как насчет этого?
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
Ответ 5
менее холодный способ, я полагаю,
; 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'