Sql 从查询中选择第一个X,但获取计数(例如分页)

Sql 从查询中选择第一个X,但获取计数(例如分页),sql,firebird,Sql,Firebird,我想返回前x行,但还需要select中的项目总数。在MSSQL中,我找到了答案,但在Interbase中,我没有找到相同的解决方案 火鸟也有这样的说法吗 还有一个普遍的问题,这种嵌入式函数(也在MSSQL中)是否比执行第二条语句来获取总行数更快?您需要两个单独的请求 一种是使用符合SQL的偏移量&获取从Firebird 3开始,或者从行子句或第一个&跳过: select field1, field2 from mytable [where conditions] [offset 0 rows]

我想返回前x行,但还需要select中的项目总数。在MSSQL中,我找到了答案,但在Interbase中,我没有找到相同的解决方案

火鸟也有这样的说法吗


还有一个普遍的问题,这种嵌入式函数(也在MSSQL中)是否比执行第二条语句来获取总行数更快?

您需要两个单独的请求

一种是使用符合SQL的
偏移量
&
获取
从Firebird 3开始,或者从
子句或
第一个
&
跳过
:

select field1, field2
from mytable
[where conditions]
[offset 0 rows] fetch first 10 rows only
另一个是接收总记录计数:

从mytable[其中的条件]中选择count(*)

注意,对于复杂的查询和/或大量数据,最后一次查询可能代价高昂。通常对大量数据使用另一种方法。一种是专用的FTS引擎,如SphinxSearch。
例如,谷歌为您提供一个大致的结果计数。

如果您使用的是Firebird 3,您可以使用:

这使用了Firebird 3中引入的

在早期版本中,这样做有点困难,但例如在Firebird 2.1及更高版本中,可以使用公共表表达式来避免重复查询和条件:

with actualquery as (
  select column1, column2, etc
  from sometable
  where somecondition
)
select (select count(*) from actualquery), column1, column2, etc
from actualquery
order by something
rows 10
对于Firebird 2.5,这使用了(类似于选择前10个

with query as (
    select * from RDB$RELATION_FIELDS where RDB$RELATION_NAME = 'RDB$RELATIONS' order by 1
) select 
    RDB$GET_CONTEXT('USER_TRANSACTION', current_timestamp) as "__count__",
    query.*
from query
where 
    coalesce(
        RDB$GET_CONTEXT('USER_TRANSACTION', current_timestamp), 
        (select RDB$SET_CONTEXT('USER_TRANSACTION', current_timestamp, count(*)) from query)
    ) is not null
rows 6 to 10;

如何使用MSSQL?您使用的是Firebird还是InterBase?自从19年前Firebird用叉子叉起,它们就不一样了。如果是Firebird,Firebird的哪个版本(例如在Firebird 3中,它比早期版本容易得多)?正如Dani所问的,展示一下您是如何在Microsoft SQL Server中解决这个问题的。在SQL中,它非常简单。只需将此部分添加到SELECT(在选择行时)“numberofrows=COUNT(myrow)OVER()”。实际上,如果interbase和firebird都有这样的语句(因为我使用了这两个数据库),这将是完美的,但对于开始,firebird也很好。您应该使用这些信息编辑您的问题,在任何情况下,Firebird 3都支持
COUNT(myrow)OVER()
在任何情况下,我已经删除了InterBase标记,因为必须考虑两个不同的数据库系统,这将使其太宽而无法回答(即使它们共享同一来源)。如果您还需要了解最新的InterBase版本,您应该问一个单独的问题。与Firebird文档的某些部分声称的相反,
不是符合SQL的子句。SQL标准子句是Firebird 3中引入的
offset
/
fetch
子句。奇怪的是,即使是FB核心开发人员也认为
是在与已存在的
第一批
一起实现时来自标准的。但是,事实上,从FB3来看,
fetch
将更加不可知于dbms的使用。我不确定他们为什么认为它是在SQL标准中定义的,也许它是基于SQL标准的早期草案。无论如何,
本身从来没有在最终发布的SQL标准中出现过。这是一个不错的解决方案,尽管在每行多次获取计数值没有多大意义。稍后,您需要将其“分离”或在数据/字段迭代/管理期间将其考虑在内。但是如果你想一次获得计数和数据,这就是方法。谢谢你的回答,这就是我想要的。但对于问题的另一部分,您是否知道使用select语句执行rowcount或运行一个附加查询以获得结果是否更快(或者取决于查询本身的复杂性)@Marcodor问题是,如果rowcount select在内部以某种方式进行了优化,并且没有为每一行提取数据。很遗憾,FB3 optimizer还不够聪明,请评估每一行的计数。@rimes,请使用
窗口
函数三思,在这种情况下不适用。在5.4s中,对一个包含650k条记录的表执行类似于
select count(*)over()、T.ID、T.NAME from TA_TEST T offset 100000 rows的查询,仅获取前20行。两个请求以60毫秒(数据)和计数(320毫秒)运行,结果接近0.4秒。
with query as (
    select * from RDB$RELATION_FIELDS where RDB$RELATION_NAME = 'RDB$RELATIONS' order by 1
) select 
    RDB$GET_CONTEXT('USER_TRANSACTION', current_timestamp) as "__count__",
    query.*
from query
where 
    coalesce(
        RDB$GET_CONTEXT('USER_TRANSACTION', current_timestamp), 
        (select RDB$SET_CONTEXT('USER_TRANSACTION', current_timestamp, count(*)) from query)
    ) is not null
rows 6 to 10;