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