我可以在单个查询中检索分页行和总计数吗?

问题描述 投票:5回答:3

我的网络应用程序中启用了一个基本网格,并启用了分页。使用Dapper通过Web API使用SQL数据填充此网格。在我的API控制器中,我运行两个单独的查询:一个用于提取行(显示在我的网格中),另一个用于获取记录总数(在我的分页控件中显示)。这很有效。但是,我正在尝试优化我的查询。

我的第一个提取行的查询一次只返回50行(使用OFFSETFETCH,以提供分页:

SELECT DISTINCT T_INDEX.* 
FROM T_INDEX
INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
WHERE... --a fairly complex WHERE statement
ORDER BY CallTime DESC
OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY

我的第二个查询提取所有行的计数,但使用相同的表,相同的连接和相同的WHERE子句:

SELECT COUNT(DISTINCT T_INDEX.IndexId)
FROM T_INDEX
INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
WHERE... --the same fairly complex WHERE statement

正如我所说,这是有效的。每次查询大约需要2.5秒,总共5秒以上。无论如何,时间滞后不是世界末日,但我希望将时间缩短一半。

我想知道是否有任何方法可以检索50行并检索一个查询中所有行的总数。我意识到这两个查询正在做两件事。但我的想法是,“可能”可以调整这两个查询并将它们合并为一个,因为表,连接和WHERE子句在两者之间是相同的。

sql sql-server
3个回答
1
投票

您可以尝试此查询:

SELECT *
FROM (
   SELECT *, COUNT(*) OVER () AS cnt
   FROM (
      SELECT DISTINCT T_INDEX.*, 
      FROM T_INDEX
      INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
      WHERE... --a fairly complex WHERE statement
   ) AS t1 ) AS t2
ORDER BY CallTime DESC
OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY

您可以根据确定结果集中的不同记录的内容来简化上述查询。


0
投票
SELECT DISTINCT T_INDEX.*,
        (SELECT COUNT(DISTINCT T_INDEX.IndexId)  FROM T_INDEX
           INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = 
           T_INDEXCALLER.IndexIdAS) AS  TotalCount
FROM T_INDEX
INNER JOIN T_INDEXCALLER ON T_INDEX.IndexId = T_INDEXCALLER.IndexId
WHERE... --a fairly complex WHERE statement
ORDER BY CallTime DESC
OFFSET (@offset) ROWS FETCH NEXT 50 ROWS ONLY

0
投票

我提出另一种解决方案:不要盲目优化。

你只是想变得幸运 - 这是不合理的。

他们没有做同样的事情,因此他们可能会单独进行优化。但更重要的是,你的两个查询都是针对2.5秒执行的,这对于只有简单连接的查询看起来很奇怪,而且只需要获取50 recordscount all。我知道这取决于表的大小和服务器的硬件,但仍然如此。

所以我认为你可以优化它们,并且不需要将它们“合并”成一个。

我先看一下查询执行计划。我很确定它可以大大加快。所以,请将查询计划添加到您的问题中。

但即使没有疑问,我也有一些问题:

  • 为什么distinct
  • 你有T_INDEX.CallTime的索引吗?
© www.soinside.com 2019 - 2024. All rights reserved.