2016-04-07 27 views
2

Birden çok ilişkiye sahip iki tablo var ve 'çok' tablosundaki belirli bir satırı bir satırdaki bir satıra kadar takip eden bir sorguyu bir araya getirmek istiyorum. 'bir masa.SQL: birleştirilmiş bir tabloyu filtrele

kullanıcı tablosu:

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

Mesajlar tablosu: Ben kullanıcı için en son mesajı almak için tek bir iletilere kullanıcıdan katılmak gerçekleştirmeye çalışıyorum

╔════╦══════════════╦═══════════╦═════════╗ 
║ 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 ║ 
╚════╩══════════════╩═══════════╩═════════╝ 

. kullanıcı 2 'test mesajı' olurdu, kullanıcı 3 'başka bir test' olurdu. Kullanıcı 1, anlayamadığım bir şey - Kullanıcı 1 için bir satırın, en son tarihe sahip olduğu gerçeğine dayanarak, 'dünya' döndürdüğünü, ancak gerçekleştirme yeteneğine sahip bir birleştirmeyi görmüyorum. birleştirilmiş tablo üzerinde filtreleme. Böyle

+0

Bunu alt sorgular veya pencere işlevleri kullanarak oldukça kolay yapabilirsiniz, ancak sözdizimi, kullanmakta olduğunuz SQL'in türüne tamamen bağlıdır. Bunu hangi dil ile yapmaya çalışıyorsun? –

+1

Hangi DBMS'yi kullanıyorsunuz? –

+0

SQL Server 2012'deyim ... Size önerdiğim gibi, 'pencere fonksiyonları' na bakıyorum, Rodkey ve web'de gördüğüm açıklamaları ve aşağıdaki önerileri temel aldım, bence cevap bu. – user856358

cevap

2

deneyin şey: SQL Server 2012 ve daha yeni de

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 

Bu kod çalışır. Size almak için

This code work in SQL Server 2012 and newer.

+0

"En son mesaj", "message_id", yani "RANK() OVER (PARTITION BY M. [kullanıcı_kimliği] SİPARİŞİ [tarih] DESC, message_id DESC)" – Eric

+0

Evet, haklısınız. Bu varyant daha iyi olacak. Teşekkürler! –

0

şey başlatan:

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

Sen tabloları birleştirmek ve daha sonuçları filtreleyebilirsiniz:

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

Bu bir deneyin. Çalışır:

select user_ID, 
text, 
u.name, 
max(date) from user u inner join messages m on m.user_id=u.id group by user_ID, 
text, 
u.name 
İlgili konular