it-swarm.com.de

Wie erhalte ich die maximale Zeilennummer pro Gruppe/Partition in SQL Server?

Ich verwende SQL Server 2005. Ich habe eine Zahlungstabelle mit Zahlungs-IDs, Benutzer-IDs und Zeitstempeln. Ich möchte die letzte Zahlung für jeden Benutzer finden. Dies ist leicht zu suchen und eine Antwort zu finden. Ich möchte jedoch auch wissen, ob die letzte Zahlung die erste Zahlung des Benutzers ist oder nicht.

Ich habe die folgenden Angaben, die die Zahlungen der einzelnen Benutzer nummerieren:

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

Ich mache nicht den mentalen Sprung, der mich dann die höchste paymentNumber pro Benutzer auswählen lässt. Wenn ich das Obige als Unterauswahl verwende, indem ich MAX (paymentNumber) verwende und dann nach user_id gruppiere, verliere ich die von mir benötigte payment_id. Wenn ich aber auch die payment_id in die group by-Klausel einfüge, kehre ich zu einer Zeile pro Zahlung zurück. Ich bin sicher, dass ich das Offensichtliche übersehen habe. Irgendeine Hilfe?

11
DaveBurns

Versuche dies:

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       
27
Chandu

Wiederholen Sie das Gleiche.

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

Jetzt hat die letzte Zahlung reversePaymentNumber 1 und die Anzahl der Zahlungen wird paymentNumber sein.

10
btilly
; 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
2
Ben Thul
SELECT * FROM (
        SELECT ROW_NUMBER() OVER(PARTITION BY OS.ContactId ORDER BY OS.Date ASC) AS FirstRow#,
        ROW_NUMBER() OVER(PARTITION BY OS.ContactId ORDER BY OS.Date DESC) AS LastRow#,
        OS.Contactid,CONVERT(VARCHAR,OS.Date,106) 'Purchase Month',
        OS.ProductId 'MyCII Subscription/Directory', OS.Charges 'Amount(INR)',OS.Date 'RAWDate'
        FROM tblOnlineServices OS
        WHERE Date IS NOT NULL AND Contactid IN('C000013112','C000010859') 
    ) FirstPurchase 
    WHERE FirstRow# = 1 OR LastRow# = 1
    ORDER BY Contactid, RAWDate
1

Wie wäre es damit?

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
MarioVW

ein weniger cooler Weg, nehme ich an

; 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'
0
DForck42