将 LIMITed SELECT 和总 COUNT 组合在一起?

Posted

技术标签:

【中文标题】将 LIMITed SELECT 和总 COUNT 组合在一起?【英文标题】:Combining a LIMITed SELECT and a total COUNT together? 【发布时间】:2014-07-25 22:38:26 【问题描述】:

我有一个名为profile 的表,其中包含用户信息。我需要对此表进行过滤查询并获得:

    与此查询匹配的行数。 仅前 5000 个匹配行的数据。

我正在寻找一种最佳方式来做到这一点。显然,至少需要进行一次扫描才能进行计数,但理想情况下,数据库可以在进行计数时获取顶部匹配项。

以下查询给了我正确的结果,但它看起来有点 hacky。我想知道它是否可以做得更好?

WITH total AS (
     SELECT COUNT(*) AS total FROM profile 
         WHERE project_id = 1 and some_prop = 100)
SELECT total.total, full_name, other_prop 
    FROM profile
    INNER JOIN total ON 1 = 1
    WHERE project_id = 1 and some_prop = 100
    ORDER BY full_name ASC
    LIMIT 5000

有没有更有效的方法来做到这一点?

【问题讨论】:

鉴于您正在做的事情,我认为它没有什么特别的问题,但是您可以将“inner join total on 1 = 1”更改为“cross join total”,这更有意义,虽然我怀疑它会表现得更好。 基本上与此重复:***.com/questions/156114/…。但不确定 Redshift,它是过时和现代功能的奇怪组合。 您的窗口方法在 Redshift 上也是最快的(到目前为止)。 【参考方案1】:

您正在扫描同一个表两次以应用过滤器。使用下面的内容,您只需在应用过滤器后扫描表格,然后在过滤后的表格上进行总计和列出。

with s as (
    select *
    from profile 
    where project_id = 1 and some_prop = 100
), t as (
    select count(*) as total from s
)
select total, full_name, other_prop 
from s cross join t
order by full_name asc
limit 5000

窗口函数版本

select
    count(*) over() as total,
    full_name,
    other_prop 
from profile
where project_id = 1 and some_prop = 100
order by full_name asc
limit 5000

【讨论】:

谢谢,我没想过这样做。这个执行计划实际上与我之前的查询相同。它可能已经达到预期效果了。 @AndySavage 测试窗口函数版本 window 方法在查询计划上看起来好多了。太好了。

以上是关于将 LIMITed SELECT 和总 COUNT 组合在一起?的主要内容,如果未能解决你的问题,请参考以下文章

请问,如何用一条SQL查询出分页的数据和总记录数啊?MySQL的!不用存储

Oracle_多行函数

将 Microsoft Office Access 数据库引擎 2007 包含到 InstallShield Limited Edition 的安装程序中

为啥将 count(*) 添加到 select 语句会强制行存在于子查询中?

CAD库中统计PBN运行航路条数和总距离

Mechanism:Limited Direct Execution