Reputation: 1594
I've a Table as below
ID |FromId |ToId |Message|DateTime
------------------------------------------
1 |1 |2 |a |15:00
2 |1 |2 |b |15:01
3 |1 |2 |c |15:02
4 |2 |1 |d |15:03
5 |3 |1 |e |15:04
6 |3 |1 |f |15:05
7 |1 |3 |g |15:06
what I want to get is Every last message of Peers.
For example: User 1 and user 2 has 4 messages (ID:1,2,3,4) and user 1 and user 3 has 3 messages (ID:5,6,7)
I want to get only latest Message record from users, I need a SQL query which will give the result like this:
*sql code here ? -- I need this.
result (for: where UserID=1) :
ID |FromId |ToId |Message|DateTime
------------------------------------------
4 |2 |1 |d |15:03
7 |1 |3 |g |15:06
Any Ideas ? I've tried with Distinct etc. but it didn't worked somehow. Please help.
Sorry Guys I guess I forgot to mention that I need the latest record from Peer, not the latest record from one user, for example for user 1 and user 2 I need the latest record from them, no mather which one is From or which one is To.. I need the latest record from both which is ID 4 in our case no other records.
Upvotes: 1
Views: 2936
Reputation: 13486
try this:
;WITH CTE As(
select id,fromID,ToID,Message,DateTime,0 as sel from Msgs where id=1
union all
select m.id,m.fromID,m.ToID,m.Message,m.DateTime,
CASE WHEN (m.FromId =c.FromId or m.FromId =c.ToId) then 0 else 1 end as sel
from CTE c inner join Msgs m
--on (c.FromId = m.FromId and c.ToId = m.ToId) or (c.FromId = m.ToId and c.ToId = m.FromId)
on m.id=c.Id+1
)
select * from CTE where ID in (select ID-1 from CTE where sel=1)
union
select * from CTE where ID = (select max(id) from CTE)
Upvotes: 0
Reputation: 2543
create function getlastmessage(
@userid int
)
returns nvarchar(max)
as
select top(1), message from messages
where userid=@userid order by messageid desc
in the people table
select *, getlastmessage(actorid) as lastmessage from people
More info about function syntax
if you don't want to use functions
select
*,
(select top(1), message from messages
where messages.userid=people.userid order by messageid desc) as lastmessage
from people
it will be a bit messy.
Upvotes: -1
Reputation: 1487
create table Msgs (ID int primary key, FromId int, ToId int, Message nvarchar(MAX), DateTime time);
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (1 ,1 ,2 ,'a' ,'15:00');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (2 ,1 ,2 ,'b' ,'15:01');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (3 ,1 ,2 ,'c' ,'15:02');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (4 ,2 ,1 ,'d' ,'15:03');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (5 ,3 ,1 ,'e' ,'15:04');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (6 ,3 ,1 ,'f' ,'15:05');
insert into Msgs (ID, FromId, ToId, Message, Datetime) values (7 ,1 ,3 ,'g' ,'15:06');
select * from Msgs;
with M(ID, FromId, ToId, Message, DateTime, RN) as (
select ID, FromId, ToId, Message, DateTime,
ROW_NUMBER() over (partition by
CASE WHEN FromId < ToID THEN FromId ELSE ToID END,
CASE WHEN FromId > ToID THEN FromId ELSE ToID END
order by DateTime desc)
from Msgs)
select ID, FromId, ToId, Message, DateTime from M where RN = 1;
drop table Msgs;
Returns
ID FromId ToId Message DateTime
1 1 2 a 15:00:00.0000000
2 1 2 b 15:01:00.0000000
3 1 2 c 15:02:00.0000000
4 2 1 d 15:03:00.0000000
5 3 1 e 15:04:00.0000000
6 3 1 f 15:05:00.0000000
7 1 3 g 15:06:00.0000000
ID FromId ToId Message DateTime
4 2 1 d 15:03:00.0000000
7 1 3 g 15:06:00.0000000
Upvotes: 0
Reputation: 19346
If Sql Server 2005+, you might use row_number() over ( ... ) to group, order and number records, and then retrieve only the ones being first in their group:
; with cte as
(
select *,
-- Group by user not being searched for
row_number() over (partition by case when FromID = @UserID
then ToID
else FromID
end
-- Last date will be numbered as 1
order by [DateTime] desc
) rn
from Table1
-- Filter only messages sent from or received by certain user
where (FromID = @UserID or ToID = @UserID)
)
select *
from cte
-- Get last dates only
where rn = 1
Upvotes: 6
Reputation: 1277
Use this Sql for this:
Declare @tempTeable Table
(
Id int,
FromID int,
ToId int,
SMessage nvarchar(250),
SDateTime Time
)
Insert into @tempTeable values(1,1,2,'a','15:00')
Insert into @tempTeable values(2,1,2,'b','15:01')
Insert into @tempTeable values(3,1,2,'c','15:02')
Insert into @tempTeable values(4,2,1,'d','15:03')
Insert into @tempTeable values(5,3,1,'e','15:04')
Insert into @tempTeable values(6,3,1,'f','15:05')
Insert into @tempTeable values(7,1,3,'g','15:06')
select distinct t1.* from @tempTeable as t1
inner join
(select UserID,MAX(SDateTime)as SDateTime from
(
select FromId as UserId ,MAX(SDateTime)as SDateTime from @tempTeable group by
FromId
UNION
select ToId as UserId,MAX(SDateTime)as SDateTime from @tempTeable group by
ToId) as tbl
group by UserId) as tblres
on (t1.FromID =tblres.UserId or t1.toId =tblres.UserId)
and t1.SDateTime=tblres.SDateTime
Upvotes: 2
Reputation: 3432
You need to do a self-referential join, so the inner query selects the max per group, and the outer query selects all the data for each row that matches.
select *
from thetable t1
join(select max(ID) as id,
FromID
from thetable
group by FromID)t2 on (t1.id=t2.id);
Upvotes: 0