2009-06-21 4 views
2

Vielleicht einen wirklich schlechten Tag bin ich zu haben, aber könnte jemand vielleicht helfen mir, dies zu machen:SQL Gruppierung: Neue Bilanz zwischen Benutzer

MessageID | SendingUserID | ReceivingUserID 
------------------------------------------- 
1073  | 1002   | 1001 
1065  | 1001   | 1002 
1076  | 1008   | 1002 

In:

MessageID | SendingUserID | ReceivingUserID 
------------------------------------------- 
1073  | 1002   | 1001 
1076  | 1008   | 1002 

Wodurch nur Die letzte Nachricht zwischen zwei Benutzern wird aufgelistet?

Antwort

0

try this:

SELECT Message.* 
FROM Message 
WHERE Message.MessageID IN 
(SELECT MAX(MessageID) FROM Message 
    GROUP BY 
     CASE WHEN ReceivingUserID > SendingUserID 
      THEN ReceivingUserID ELSE SendingUserID END, 
     CASE WHEN ReceivingUserID > SendingUserID 
      THEN SendingUserID ELSE ReceivingUserID END 
) 
+0

aktualisiert, um der Anforderung "zwischen zwei Benutzern" zu entsprechen; @unknown: Sie können SendingUserID ohne Aggregation und ohne GroupBy nicht auswählen – devio

+0

Sie können, aber das Ergebnis wird für diese Spalten nicht deterministisch sein, wenn sie innerhalb der Partition nicht konstant sind. –

+0

Danke für dein Beispiel, es funktioniert, obwohl ich ein wenig verwirrt bin von der Gehäuse in der Gruppe, beide sind die gleichen - ist das richtig? – Nathan

0

Die exklusive Selbst Ansatz verbinden:

select * 
from YourTable a 
left join YourTable b 
    on (
     (a.SendingUserID = b.SendingUserID 
     and a.ReceivinggUserID = b.ReceivingUserID) 
     or (a.SendingUserID = b.ReceivingUserID 
     and a.ReceivinggUserID = b.SendingUserID) 
    ) and b.messageid > a.messageid 
where b.messageid is null 

Die Join auf "b" sucht für die späteren Nachrichten zwischen den gleichen Benutzern. Die WHERE-Klausel filtert Nachrichten, die keine spätere Nachricht enthalten. Dies gibt Ihnen nur die letzte Nachricht zwischen jedem Benutzerpaar.

0

Sie könnten einen CTE (Common Table Expression) verwenden in SQL Server 2005 und höher zu machen, dass die beiden UserID ist immer der kleinere vor dem größeren, und dann bekommen nur das Maximum für jede dieser Kombinationen:

WITH Messages(MessageID, User1, User2) 
AS 
(
    SELECT 
     MessageID, 
     CASE 
      WHEN SendingUserID < ReceivingUserID 
      THEN SendingUserID 
      ELSE ReceivingUserID 
     END as 'User1', 
     CASE 
      WHEN SendingUserID < ReceivingUserID 
      THEN ReceivingUserID 
      ELSE SendingUserID 
     END as 'User2' 
    FROM 
     MyMessages 
) 
SELECT 
    MessageID, User1, User2 
FROM 
    Messages m1 
WHERE 
    MessageID = (SELECT MAX(MessageID) FROM Messages m2 
       WHERE m1.User1 = m2.User1 AND m1.User2 = m2.User2) 

der innere SELECT innerhalb des CTE würde Ihre Nachrichten wie diese „bestellen“:

MessageID User1 User2 
    1065  1001 1002 
    1073  1001 1002 
    1076  1002 1008 

und die äußeren SELECT auf der Grundlage dieses CTE nimmt dann einfach nur den Eintrag mit den maximalen MessageID für jeden com bination von (Benutzer1, Benutzer2).

Marc