【问题标题】:Efficiently determine if any rows satisfy a predicate in Postgres有效地确定是否有任何行满足 Postgres 中的谓词
【发布时间】:2015-12-09 20:10:48
【问题描述】:

我想查询数据库是否存在一个或多个满足给定谓词的行。但是,我对存在这样的一行、两行或一百万行之间的区别不感兴趣——只要有“零”或“一个或多个”。而且我不希望 Postgres 浪费时间生成我不需要的精确计数。

在 DB2 中,我会这样做:

SELECT 1 FROM SYSIBM.SYSDUMMY1 WHERE EXISTS 
(SELECT 1 FROM REAL_TABLE WHERE COLUMN = 'VALUE')

然后检查查询返回的是零行还是一行。

但是 Postgres 没有可用的虚拟表,那么最好的选择是什么?

如果我自己创建一个单行虚拟表并使用它来代替 SYSIBM.SYSDUMMY1,查询优化器是否足够聪明以至于在运行查询时不会实际读取该表,否则会“做正确的事”?

【问题讨论】:

    标签: sql postgresql exists


    【解决方案1】:

    如果您对“没有行”感到满意,如果没有行匹配,您甚至可以:

    SELECT 1 FROM real_table WHERE column = 'VALUE' <b>LIMIT 1</b>;

    性能与EXISTS基本相同。大表性能的关键是匹配索引。

    【讨论】:

      【解决方案2】:

      这样做怎么样?

      SELECT (CASE WHEN EXISTS (SELECT 1 FROM REAL_TABLE WHERE COLUMN = 'VALUE') THEN 1 ELSE 0 END)
      

      1 表示有值。 0 表示没有价值。

      这将始终返回一行。

      【讨论】:

      • 这不会总是返回一行,如果子查询匹配多行就会返回错误。
      • 感谢 Gordon Linoff 的建议,但是在表有多个满足谓词的行的情况下,我收到错误“子查询返回的不止一行用作表达式” ,这对我来说表明 Postgres 在找到第一行后不会停止处理查询。
      【解决方案3】:

      PostgreSQL 没有虚拟表,因为您不需要。

      SELECT 1 WHERE EXISTS 
      (SELECT 1 FROM REAL_TABLE WHERE COLUMN = 'VALUE')
      

      或者,如果您想要一个真/假答案:

      SELECT EXISTS(SELECT 1 FROM REAL_TABLE WHERE COLUMN = 'VALUE')
      

      【讨论】:

      • 耐人​​寻味,尤其是第二个。它确实返回了预期的结果。我无法测试效率,因为这些 Postgres 表中还没有真正的生产数据,但是语法非常简单,查询优化器应该不会出错。
      猜你喜欢
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2019-08-20
      相关资源
      最近更新 更多