19

我有一个搜索屏幕,用户可以在其中搜索 5 个过滤器。
我基于这些过滤器值构建了一个动态查询,并且一次生成了第 10 页的结果。
这在 SQL2012 中使用OFFSETand运行良好FETCH,但我使用两个查询来执行此操作。

我想显示 10 个结果显示查询找到的总行数(比如说 1000)。
目前我通过运行两次查询来做到这一点- 一次用于总计数,然后再次对 10 行进行分页。
有没有更有效的方法来做到这一点?

4

5 回答 5

27

您不必运行两次查询。

SELECT ..., total_count = COUNT(*) OVER()
FROM ...
ORDER BY ...
OFFSET 120 ROWS
FETCH NEXT 10 ROWS ONLY;

根据chat,您的问题似乎有点复杂 -DISTINCT除了分页之外,您还应用了结果。这会使准确确定COUNT()应该是什么样子以及应该去哪里变得复杂。这是一种方法(我只是想证明这一点,而不是尝试将该技术合并到来自聊天的更复杂的查询中):

USE tempdb;
GO
CREATE TABLE dbo.PagingSample(id INT,name SYSNAME);

-- insert 20 rows, 10 x 2 duplicates
INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns;
INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns;

SELECT COUNT(*) FROM dbo.PagingSample; -- 20

SELECT COUNT(*) FROM (SELECT DISTINCT id, name FROM dbo.PagingSample) AS x; -- 10

SELECT DISTINCT id, name FROM dbo.PagingSample; -- 10 rows

SELECT DISTINCT id, name, COUNT(*) OVER() -- 20 (DISTINCT is not computed yet)
 FROM dbo.PagingSample
 ORDER BY id, name
 OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY; -- 5 rows

-- this returns 5 rows but shows the pre- and post-distinct counts:
SELECT PostDistinctCount = COUNT(*) OVER() -- 10, 
  PreDistinctCount -- 20, 
  id, name 
FROM 
(
  SELECT DISTINCT id, name, PreDistinctCount = COUNT(*) OVER() 
    FROM dbo.PagingSample
    -- INNER JOIN ...
) AS x
ORDER BY id, name
OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY;

清理:

DROP TABLE dbo.PagingSample;
GO
于 2013-10-01T20:39:09.403 回答
5

我的解决方案类似于“rs. answer”

DECLARE @PageNumber AS INT, @RowspPage AS INT
SET @PageNumber = 2
SET @RowspPage = 5 

SELECT   COUNT(*) OVER() totalrow_count,*
    FROM databasename
    where columnname like '%abc%'
    ORDER BY columnname
    OFFSET ((@PageNumber - 1) * @RowspPage) ROWS
    FETCH NEXT @RowspPage ROWS ONLY;

返回结果将包括 totalrow_count 作为第一列名称

于 2014-12-29T08:21:00.357 回答
3

你能试试这样的吗

SELECT TOP 10 * FROM 
(
   SELECT COUNT(*) OVER() TOTALCNT, T.*
   FROM TABLE1 T
   WHERE col1 = 'somefilter'
) v

或者

SELECT * FROM 
(
   SELECT COUNT(*) OVER() TOTALCNT, T.*
   FROM TABLE1 T
   WHERE col1 = 'somefilter'
) v
ORDER BY COL1
OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY

现在您的 totalcnt 列中有总数,您可以使用此列显示总行数

于 2013-10-01T20:39:09.053 回答
2

在我使用复杂连接和返回约 6,000 条记录的测试中,执行两个单独的查询要快得多。更快,以毫秒为单位获取总数并分别带回 100 条记录的子集,而执行组合查询需要 17 秒。其他人看到这种性能冲击吗?显然,它可能与数据结构有关,但这仍然是一个巨大的差异。

于 2021-05-14T13:56:44.597 回答
1

我希望我现在回答这个问题还为时不晚,但今晚我遇到了一个非常相似的问题。我有一个分页类过度夸大了返回的结果数量,因为以前的开发人员正在删除 DISTINCT 并且只是执行表连接的 SELECT count(*)。虽然这不能解决 2 查询问题,但我最终使用了嵌套查询,因此它看起来像这样:

原始查询

SELECT DISTINCT
  field1, field2
FROM
  table1 t1
  left join table2 t2 on t2.id = t1.id

过度膨胀的结果查询

SELECT
  count(*)
FROM
  table1 t1
  left join table2 t2 on t2.id = t1.id

我的结果查询解决方案

SELECT
  count(*)
FROM
  (SELECT DISTINCT
     field1, field2
   FROM
     table1 t1
     left join table2 t2 on t2.id = t1.id) as tbl;
于 2013-12-03T04:26:52.533 回答