1

私は以下のような表を持っています

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

私が取得したいのは、ピアのすべての最後のメッセージです。

例:ユーザー1とユーザー2には4つのメッセージ(ID:1,2,3,4)があり、ユーザー1とユーザー3には3つのメッセージ(ID:5,6,7)があります。

ユーザーから最新のメッセージレコードのみを取得したいのですが、次のような結果が得られるSQLクエリが必要です。

*sql code here ? -- I need this.

結果(for:ここでUserID = 1):

ID  |FromId |ToId   |Message|DateTime
------------------------------------------
4   |2      |1      |d      |15:03
7   |1      |3      |g      |15:06

何か案は ?Distinctなどで試してみましたが、どういうわけかうまくいきませんでした。助けてください。

申し訳ありませんが、たとえばユーザー1とユーザー2の場合、1人のユーザーからの最新のレコードではなく、ピアからの最新のレコードが必要であることを忘れてしまったと思います。 To..両方の最新のレコードが必要です。この場合はID4で、他のレコードはありません。

4

6 に答える 6

6

Sql Server 2005以降の場合は、row_number()over(...)を使用してレコードをグループ化し、順序付けして番号を付け、グループの最初のレコードのみを取得できます。

; 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
于 2012-09-11T11:39:07.267 に答える
2

これには、このSQLを使用します。

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 
于 2012-09-11T11:29:09.600 に答える
0
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;

戻り値

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
于 2012-09-11T11:43:04.643 に答える
0

自己参照結合を実行する必要があるため、内部クエリはグループごとの最大値を選択し、外部クエリは一致する各行のすべてのデータを選択します。

select * 
from thetable t1 
join(select max(ID) as id,
            FromID 
     from thetable
     group by FromID)t2 on (t1.id=t2.id);
于 2012-09-11T11:12:09.867 に答える
0

これを試して:

;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)
于 2012-09-11T12:08:48.687 に答える
-1
create function getlastmessage(
@userid int
)
returns nvarchar(max)
as
select top(1), message from messages 
 where userid=@userid order by messageid desc

人々のテーブルで

select *, getlastmessage(actorid) as lastmessage from people

関数構文に関する詳細情報


関数を使いたくない場合

select 
*, 
(select top(1), message from messages 
  where messages.userid=people.userid order by messageid desc) as lastmessage 
 from people

少し面倒になります。

于 2012-09-11T11:11:35.180 に答える