我必须查询一个表,其中包含几百万行的行,并且我想对其进行最优化的查询。
假设我们要控制具有多个放映厅的电影院的访问权限,并保存如下:
AccessRecord
(TicketId,
TicketCreationTimestamp,
TheaterId,
ShowId,
MovieId,
SeatId,
CheckInTimestamp)
为简化起见,数据类型为“ bigint”和“时间戳”的“ Id”列为“ datetime”。门票随时出售,人们可以随意进入剧院。主键(也是唯一的)是TicketId。
我想为每个电影和剧院及表演(时间)获取访问剧院观看电影的第一个和最后一个人的AccessRecord信息。如果两个签到同时发生,我只需要1个即可。
我的解决方案是在子查询中连接PK和分组列以获取行:
select
AccessRecord.*
from
AccessRecord
inner join(
select
MAX(CONVERT(nvarchar(25),CheckInTimestamp, 121) + CONVERT(varchar(25), TicketId)) as MaxKey,
MIN(CONVERT(nvarchar(25),CheckInTimestamp, 121) + CONVERT(varchar(25), TicketId)) as MinKey
from
AccessRecord
group by
MovieId,
TheaterId,
ShowId
) as MaxAccess
on CONVERT(nvarchar(25),CheckInTimestamp, 121) + CONVERT(varchar(25), TicketId) = MaxKey
or CONVERT(nvarchar(25),CheckInTimestamp, 121) + CONVERT(varchar(25), TicketId) = MinKey
转换121是对数据时间的规范表达式,其重排方式如下:aaaa-mm-dd hh:mi:ss.mmm(24h),因此按字符串数据类型进行排序,将得到与按日期时间排序相同的结果。
如您所见,这种联接不是非常优化,有什么想法吗?
更新我如何测试不同的解决方案:
我已经使用SQL Server 2008 R2在一个具有超过3M行的表的真实数据库中测试了所有答案,以选择正确的答案。
如果我只获得第一个或最后一个访问者:
如果我进行相同的访问,但分组列的结果是有序的:
如果我同时获得(第一个和最后一个)访问结果的人:
其余解决方案(甚至是我的解决方案)在第一次测试中持续超过60秒,因此我取消了它。
尝试这个:
select a.*
from AccessRecord a
where not exists(
select 'next'
from AccessRecord a2
where a2.movieid = a.movieid
and a2.theaterid = a.theaterid
and a2.showid = a.showid
and a2.checkintimestamp > a.checkintimestamp
)
这样,您就可以为同一部电影前戏选择最后一行作为时间戳。
每行票(我想)是不同的
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句