PostgreSQL 公共表表达式与临时表?

Nat*_*ong 14 postgresql

WITH 上PostgreSQL 文档显示了以下示例:

WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;
Run Code Online (Sandbox Code Playgroud)

它还指出:

WITH 查询的一个有用特性是,它们在每次执行父查询时仅被评估一次,即使它们被父查询或同级 WITH 查询多次引用。

我看到它WITH可以用于其他事情,比如递归评估。但是在上面的例子中,使用WITH和创建临时表有什么重要的区别吗?

Cra*_*ger 19

有一些细微的差异,但没有太大的区别:

  • 您可以在临时表上添加索引;
  • 临时表存在于会话(或 if ON COMMIT DROP,事务)的生命周期内,而WITH始终严格限定在查询范围内;
  • 如果查询调用的函数/程序,它可以看到临时表,但能不能看到任何WITH表表达式;
  • 临时表VACUUM在系统目录上生成工作WITH,但它不需要额外的往返来创建/填充它,并且需要在服务器的缓存管理中进行额外的工作,因此效率稍低。

总的来说,您应该更喜欢WITH临时表,除非您知道您将从创建索引中受益。

然而,另一个选项,FROM子句中的子查询,有一组非常不同的优点。特别是它可以被内联,并且限定符可以被上拉/下推。我在最近的一篇博客文章中写到了这一点。