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

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

  1. 与此查询匹配的行数。
  2. 仅前 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”,这更有意义,虽然我怀疑它会表现得更好。
  • 基本上与此重复:stackoverflow.com/questions/156114/…。但不确定 Redshift,它是过时和现代功能的奇怪组合。
  • 您的窗口方法在 Redshift 上也是最快的(到目前为止)。

标签: sql postgresql amazon-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 方法在查询计划上看起来好多了。太好了。
猜你喜欢
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 2018-07-27
  • 2018-07-09
相关资源
最近更新 更多