Sql 是否可以在没有分组依据的情况下编写此查询
DirectionId只包含值1(I-输入)和2(O-输出)。TypeId目前包含10种类型。DirectionId和typeId是其代码列表的外键。表消息当前包含超过360万条记录。我添加了适当的索引,可以执行1.5秒以上的查询,但我希望它更快。索引定义:Sql 是否可以在没有分组依据的情况下编写此查询,sql,group-by,Sql,Group By,DirectionId只包含值1(I-输入)和2(O-输出)。TypeId目前包含10种类型。DirectionId和typeId是其代码列表的外键。表消息当前包含超过360万条记录。我添加了适当的索引,可以执行1.5秒以上的查询,但我希望它更快。索引定义: select MAX(date), TypeId, DirectionId from mqview.[Message] where RecActive = 1 group by TypeId, DirectionId 对每个TypeId
select MAX(date), TypeId, DirectionId
from mqview.[Message]
where RecActive = 1
group by TypeId, DirectionId
对每个TypeId执行都很快(仅遍历索引树)
但是类型代码列表包含10个类型,所以这需要20个查询(方向是2的倍)。我认为group by的延迟最大。有没有一种不用分组就能重写的方法
我正在使用Microsoft SQL Server 2014
更新
我用来获取结果的查询现在实际上是这样的:
select top 1 * from mqview.Message where RecActive = 1 and TypeId = 2 and DirectionId = 1 order by id desc
在添加Gordon Linoff建议的索引(略有不同)后,查询现在执行~1s
select m.Date as 'Date', t.Code as 'Type', d.Code as 'Direction'
from
mqview.Message m
inner join mqview.MessageType t on (t.id = m.TypeId)
inner join mqview.MessageDirection d on (d.Id = m.DirectionId)
where
t.Visible = 1
and m.Id in (
SELECT
MAX(Id)
FROM
mqview.[Message]
where
RecActive = 1 and Date is not null
GROUP BY
TypeId,
DirectionId
)
我不确定是否需要
include(id)
。如果没有include(id)
索引指向RowID(它指向表行),使用include(id)
索引存储id(因此覆盖索引),但是在没有include(删除索引,创建新索引)的情况下运行查询不会产生时间差异。如果我不得不推测,问题是where
子句。尝试创建包含该子句的索引:
create index covering_index ON [mqview].[Message] (RecActive, Date desc, TypeId, DirectionId,) include (id);
或者,为了更好地使用现有索引,请切换到条件聚合:
create index covering_index ON [mqview].[Message] (RecActive, TypeId, DirectionId, [Date] desc) ;
当您独立地对每种类型进行查询时,类型和方向以及where
子句中的条件,所有子句都通过和
s进行相等比较。因此,优化器可以使用现有索引,在数据页中查找RecActive
您的问题的答案是,还有其他方法可以编写查询,但是如果没有正确的索引,它们可能会有相同的问题。一个想法是使用相关子查询:
select max(case when RecActive = 1 then date end), TypeId, DirectionId
from mqview.[Message]
group by TypeId, DirectionId;
如果您有类型和方向的列表:
select m.*
from mqview.[Message] m
where m.RecActive = 1 and
m.date = (select max(m2.date)
from mqview.[Message] m2
where m2.RecActive = 1 and m2.typeid = m.typeid and m2.directionid = m.directionid
);
我认为使用适当的索引分区会更快。试试这个
select t.typeid, d.directionid, m.date
from types t cross join
dimensions d cross apply
(select top 1 m.date
from mqview.[Message] m
where m.typeid = t.typeid and m.directionid = d.directionid and
RecActive = 1
order by date desc
) m;
试试这个:
; WITH CTE AS
(
SELECT IIF(RecActive = 1, date, ''), TypeID, DirectionId, ROW_NUMBER() OVER (PARTITION BY TypeID, DirectionID ORDER BY date DESC)
FROM mqview.[Message]
)
SELECT * FROM CTE CTE
WHERE CTE.RN = 1
您正在使用什么样的sql?是的,使用相关子查询。但它很可能会更慢。您使用的是哪种DBMS?有其他方法,但没有上述方法优化或有效。使用分区方式如何???smart在日期上描述。。。。这也可以通过CTE解决,因为相关子查询具有相似的执行时间,或者执行时间稍长一些。但是谢谢你的选择。
; WITH CTE AS
(
SELECT IIF(RecActive = 1, date, ''), TypeID, DirectionId, ROW_NUMBER() OVER (PARTITION BY TypeID, DirectionID ORDER BY date DESC)
FROM mqview.[Message]
)
SELECT * FROM CTE CTE
WHERE CTE.RN = 1
select max.date, T.* from
(select distinct TypeId, DirectionId from mqview.[Message] where RecActive = 1) T
outer apply (select top 1 date from mqview.[Message] where RecActive = 1 and T.TypeID = TypeID and T.DirectionId = DirectionID order by date desc ) max