【问题标题】:Select only partial result but get total number of rows仅选择部分结果但获得总行数
【发布时间】:2013-07-18 21:47:38
【问题描述】:

我卡在 SQL 子查询选择上。现在,我有一个表产品:

 id | name  |     description      
----+-------+----------------------
  6 | 123   | this is a           +
    |       | girl.
  7 | 124   | this is a           +
    |       | girl.
  8 | 125   | this is a           +
    |       | girl.
  9 | 126   | this is a           +
    |       | girl.
 10 | 127   | this is a           +
    |       | girl.
 11 | 127   | this is a           +
    |       | girl. Isn't this?
 12 | 345   | this is a cute slair
 13 | ggg   | this is a           +
    |       | girl
 14 | shout | this is a monster
 15 | haha  | they are cute
 16 | 123   | this is cute

我要做的是找到(记录总数前5条记录 ) 在 namedescription 列中包含 '1''this'

我能想到的太丑了:

SELECT *, (select count(id)
           from (SELECT * from products
                 where description like any (array['%1%','%this%'])
                           or name like any (array['%1%','%this%'])
                ) as foo
          ) as total
from (SELECT * from products
      where description like any (array['%1%','%this%'])
                or name like any (array['%1%','%this%']))
     ) as fooo
limit 5;

【问题讨论】:

  • 为什么不运行 2 个单独的查询?
  • @Yuriy 谢谢,你能给我举个例子吗?
  • simple 运行第一个仅返回 count 且没有任何 WHERE 条件或 LIMIT 限制的查询;第二个查询返回所有列,但将它们限制为 5 条记录并使用您的 WHERE 条件
  • @YuriyGalanter 感谢您的回复。我想过,但实际上有100000多条记录,我问了这个问题,有人说我不应该把它们都归还,因为要统计它们
  • 您想要qualifying 记录的总数还是表中的记录总数?我假设是前者,这意味着@Yuiy 的评论需要include WHERE 子句。否则,这是一个有效的解决方案,它返回所有记录,只返回计数。

标签: sql postgresql count pattern-matching window-functions


【解决方案1】:

您可以使用聚合函数count()作为窗口函数来计算同一查询级别的总计数:

SELECT id, name, description, count(*) OVER () AS total
FROM   products p
WHERE  description LIKE ANY ('{%1%,%this%}'::text[])
           OR name LIKE ANY ('{%1%,%this%}'::text[])
ORDER  BY id
LIMIT  5;

引用manual on window functions

除了这些函数之外,任何内置或用户定义的聚合函数都可以用作窗口函数

这是可行的,因为LIMIT 是在 窗口函数之后应用的。

我还为数组文字使用了另一种语法。一个和另一个一样好。对于更长的阵列,这个更短。有时需要显式类型转换。我在这里假设text

在我的测试中,它比带有 CTE 的版本更简单、更快。

顺便说一句,这个带有正则表达式的 WHERE 子句更短 - 但更慢:

WHERE  description ~ '(1|this)'
           OR name ~ '(1|this)'

丑陋,但速度很快

另一个测试:我发现原始版本(类似于您已经拥有的)甚至更快

SELECT id, name, description
    , (SELECT count(*)
       FROM   products p
       WHERE  description LIKE ANY ('{%1%,%this%}'::text[])
                  OR name LIKE ANY ('{%1%,%this%}'::text[])
      ) AS total
FROM   products p
WHERE  description LIKE ANY ('{%1%,%this%}'::text[])
           OR name LIKE ANY ('{%1%,%this%}'::text[])
ORDER  BY id
LIMIT  5;

【讨论】:

    【解决方案2】:

    假设您使用的是 postgresql 9.0+,您可以为此使用 CTE。 例如。

    WITH p AS (
            SELECT *
            FROM products
            WHERE description LIKE ANY (ARRAY['%1%','%this%']) OR name LIKE ANY (ARRAY['%1%','%this%'])
            )
    SELECT  *,
            (select count(*) from p) as total
    FROM p
    ORDER BY id LIMIT 5;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-01
      • 1970-01-01
      • 2019-04-20
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 2010-12-06
      相关资源
      最近更新 更多