2016-04-07 24 views
2

Ich habe zwei Tabellen, die eine eins-viele Beziehung haben, und ich möchte eine Abfrage, die eine Regel folgt, um eine bestimmte Zeile in der 'viele' Tabelle zu einer Zeile in der 'ein Tisch.SQL: filter eine verbundene Tabelle

Benutzertabelle:

╔════╦══════════════╦ 
║ id ║ name  ║ 
╠════╬══════════════╬ 
║ 1 ║ user 1  ║ 
║ 2 ║ user 2  ║ 
║ 3 ║ user 3  ║ 
║ 4 ║ user 4  ║ 
╚════╩══════════════╩ 

Nachrichten Tabelle:

╔════╦══════════════╦═══════════╦═════════╗ 
║ id ║ Text  ║ user_id ║ date ║ 
╠════╬══════════════╬═══════════╬═════════╣ 
║ 1 ║ Hello  ║ 1  ║ 3/31 ║ 
║ 2 ║ World  ║ 1  ║ 4/1 ║ 
║ 3 ║ Test message ║ 2  ║ 4/2 ║ 
║ 4 ║ Another test ║ 3  ║ 4/4 ║ 
╚════╩══════════════╩═══════════╩═════════╝ 

Ich versuche, eine einzige von Benutzer zu Meldungen kommen auszuführen, um die jüngste Nachricht für den Benutzer zu erhalten. Benutzer 2 hätte eine Testnachricht, Benutzer 3 hätte einen anderen Test. Benutzer 1 ist derjenige, den ich nicht herausfinden kann - Ich hätte gerne eine Zeile für Benutzer 1 zurückgegeben "Welt", basierend auf der Tatsache, dass es das neueste Datum hat, aber ich sehe keine Verknüpfung, die die Fähigkeit zu erfüllen hat Filtern auf einer verbundenen Tabelle.

+0

Sie können dies relativ einfach mit Unterabfragen oder Fensterfunktionen tun, aber die Syntax beruht vollständig auf der Art von SQL, die Sie verwenden. Mit welcher Sprache versuchen Sie das? –

+1

Welche DBMS benutzen Sie? –

+0

Ich bin auf SQL Server 2012 ... Ich schaue auf "Fensterfunktionen", wie Sie empfehlen, Rodkey, und basierend auf den Beschreibungen, die ich im Web und die Vorschläge unten sehe, denke ich, dass das die Antwort ist. – user856358

Antwort

2

versuchen, etwas wie folgt aus:

SELECT 
    message_id 
    , [user_id] 
    , name 
    , [Text] 
    , [date] 
FROM 
(
SELECT 
    M.id AS message_id 
    , U.id AS [user_id] 
    , name 
    , [Text] 
    , [date] 
    --Rank rows for each users by date 
    , RANK() OVER(PARTITION BY M.[user_id] ORDER BY [date] DESC, M.id DESC) AS Rnk 
FROM 
    @messages AS M 
    INNER JOIN 
    @users AS U 
     ON M.[user_id] = U.id 
) AS Tmp 
WHERE 
    --The latest date 
    Tmp.Rnk = 1 

Dieser Code Arbeit in SQL Server 2012 und höher.

This code work in SQL Server 2012 and newer.

+0

Die "neueste Nachricht" sollte auch die 'message_id', daher' RANK() OVER (PARTITION VON M. [user_id] ORDER BY [Datum] DESC, message_id DESC) ' – Eric

+0

Ja, Sie haben Recht. Diese Variante wird besser sein. Vielen Dank! –

0

Etwas, das Sie zu erhalten begonnen:

select u.id, u.name, m.text 
from User u 
inner join Messages m on m.user_id = u.id 
inner join (
    select m.user_id, MAX(date) as max_date 
    from User u 
    inner join Messages m on m.user_id = u.id 
    group by m.user_id 
) t on t.user_id = m.user_id and m.date = t.max_date 
2

Sie die Tabellen beitreten können und als die Ergebnisse filtern:

select tbl.name , tbl.Text from 
(select User.name, 
     Messages.Text, 
     RANK() OVER (PARTITION BY User.name ORDER BY Messages.date desc) AS rank 
from User inner join Messages 
on User.id = Messages.user_id) as tbl 
where rank=1 
0

versuchen diese. Es sollte funktionieren:

Verwandte Themen