SQL从一个表中选择多个不同的记录
我有一张如下的桌子SQL从一个表中选择多个不同的记录,sql,sql-server,tsql,sql-server-2008-r2,greatest-n-per-group,Sql,Sql Server,Tsql,Sql Server 2008 R2,Greatest N Per Group,我有一张如下的桌子 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
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.
结果(对于:其中UserID=1):
有什么想法吗?我试过使用DISTINCE等,但不知怎的都没用。请帮忙
对不起,伙计们,我想我忘了提到我需要来自同行的最新记录,而不是来自一个用户的最新记录,例如,对于用户1和用户2,我需要来自他们的最新记录,不知道是来自哪个用户还是来自哪个用户。。我需要这两个数据库中的最新记录,在我们的案例中为ID 4,没有其他记录。
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
会有点乱
在人物表中
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
这将有点混乱。您需要进行自引用联接,因此内部查询选择每个组的最大值,外部查询选择匹配的每行的所有数据
select *
from thetable t1
join(select max(ID) as id,
FromID
from thetable
group by FromID)t2 on (t1.id=t2.id);
您需要执行自引用联接,因此内部查询选择每个组的最大值,外部查询选择匹配的每行的所有数据
select *
from thetable t1
join(select max(ID) as id,
FromID
from thetable
group by FromID)t2 on (t1.id=t2.id);
使用此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
使用此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
如果是Sql Server 2005+,则可以使用对记录进行分组、排序和编号,然后仅检索组中第一个记录:
; 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
如果是Sql Server 2005+,则可以使用对记录进行分组、排序和编号,然后仅检索组中第一个记录:
; 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
试试这个:
;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)
试试这个:
;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)
您使用的是哪个版本的Sql Server?我使用的是MSSQL 2008 R2您使用的是哪个版本的Sql Server?我使用的是MSSQL 2008 R2使用的函数将起作用,但是您最终会对表中的每个distinct-fromid执行一个额外的查询…您是希望执行两个查询并让服务器对两个表之间的索引执行联接,还是让N个查询运行,其中N是数据库中的distinct-id数。。随着时间的推移,您将遇到缩放问题。@Stephen第二个查询中的select(max)已经执行了N次。因此,从技术上讲,您在不同的查询上执行相同的工作,并除此之外执行联接。区别在于,我只收集了一次数据,然后执行联接。。使用函数要求您对每一行执行一个全新的查询…@Stephen问题是,当您使用group by收集数据时,执行过程采用相同的步骤。使用函数将起作用,但是您最终会对表中的每个distinct-fromid执行一个额外的查询…您是希望执行两个查询并让服务器对两个表之间的索引执行联接,还是让N个查询运行,其中N是数据库中的distinct-id数。。随着时间的推移,您将遇到缩放问题。@Stephen第二个查询中的select(max)已经执行了N次。因此,从技术上讲,您在不同的查询上执行相同的工作,并除此之外执行联接。区别在于,我只收集了一次数据,然后执行联接。。使用函数需要对每一行执行一个全新的查询…@Stephen问题是,当您使用group by收集数据时,执行过程采用相同的步骤。这是可以的,但它只从用户处获取最新消息我需要从Peer处获取最新消息这是可以的,但它只从用户处获取最新消息我需要从Peer处获取最新消息我想他需要的是所有用户的结果集,而不是一个特定用户的结果集,但不确定。@Nikola感谢您的回答。我认为这将是最好的解决方案。@adnanturken My bad,您的数据样本没有显示任何超出筛选范围的行,因此我认为您需要所有用户。:D实际上我的错误让我来解决这个问题:)我想他需要的是所有用户的结果集,而不是一个特定的用户,但不确定。@Nikola感谢您的回答。我认为这将是最好的解决方案。@adnanturken My bad,您的数据样本没有显示任何超出筛选范围的行,因此我认为您需要所有用户。:D实际上我的错误让我来解决这个问题:)工作正常,但成本比CTE版本高5倍左右。工作正常,但成本比CTE版本高5倍左右。