Sql 是否可以在没有分组依据的情况下编写此查询

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

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执行都很快(仅遍历索引树)

但是类型代码列表包含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