Psql - from 子句中的子查询 - 不好的做法?

Posted

技术标签:

【中文标题】Psql - from 子句中的子查询 - 不好的做法?【英文标题】:Psql - sub queries in from clause - bad practice? 【发布时间】:2015-11-03 01:26:37 【问题描述】:

手头的任务是选择音乐家 (pid) 和每次演奏的乐器数量,包括仅在音乐会上演奏的乐器 - 这些乐器可能不在 [plays] 表中。

我已经解决了,但我读到应该尽可能避免使用 from 子句中的子查询。只是出于好奇,谁能告诉我一个更有效的方法?或者这是一个很好的解决方案?我正在使用 psql。

select a.pid, sum(a.instr)
from 
(
    select pid, count(instr) as instr from plays group by pid
    union all
    select pid, count(instr) as instr from concert group by pid
) as a
group by a.pid;

【问题讨论】:

【参考方案1】:

这样的查询不是问题。数据库的查询优化器将负责充分利用此查询。在某些情况下,INNER JOIN 将转换为与子SELECT 完全相同的执行计划。

如果您认为查询有问题,您可以随时启动 psql 的EXPLAIN ANALYZE 函数。这将使您大致了解您的查询实际上在做什么。这样您还可以比较编写查询的不同方式。

你给出的例子......我认为没有子查询你不能很容易地解决这个问题。我认为你选择的方式很好。任何涉及LEFT JOINs 的内容都会更难阅读。

【讨论】:

更具体地说,查询计划器可以并且经常做扁平化子查询,将条件从子查询拉到外部查询,将条件从外部查询推送到子查询等。子查询大多只是符号,并且与查询的实际执行方式没有您想象的那么大的关系。至少在 PostgreSQL 中。【参考方案2】:

优势

子查询是有利的,因为它们构造查询以隔离语句的每个部分,执行通常需要复杂连接和联合的相同操作并且更易于阅读。

缺点

使用子查询时,查询优化器可能需要执行额外的步骤,因此它们的执行时间比连接要长。

对父查询的每一行执行一次不相关的子查询。如果这种子查询处理大量数据,您应该预计处理数据需要很长时间。

可能的解决方案:

您可以创建临时表来存储子查询的数据,然后使用 JOIN 来完成查询。请记住,使用 JOIN 比使用子查询更好。 How to Create a Table

使用 with 子句。 WITH 提供了一种编写辅助语句以用于更大查询的方法。这些语句,通常被称为公用表表达式或 CTE,可以被认为是定义仅用于一个查询的临时表。它允许您只执行一次子查询,而不是为每一行执行它。 How to Use With Clause

注意:您应该避免使用 UNION 或 UNION ALL。

【讨论】:

你的缺点不正确。相关子查询对外部查询中的每一行执行一次,但不相关子查询不会。临时表通常较慢且不必要,因为您可以使用 CTE,由于优化器防护也存在问题。这确实不准确。就此而言,优势部分也不正确,因为优化器可以拉起、下推和展平子查询。

以上是关于Psql - from 子句中的子查询 - 不好的做法?的主要内容,如果未能解决你的问题,请参考以下文章

使用 from 子句中的子查询动态选择表名

View 的 SELECT 包含 FROM 子句中的子查询

使用 FROM 子句中的子查询进行联接操作中的 SQL 语法错误

带有联合错误的 MySQL 视图 - “视图的 SELECT 包含 FROM 子句中的子查询”

MYSQL 获取最低值的记录 | View 的 SELECT 包含 FROM 子句中的子查询

在 MS Query 中使用多个 INNER JOIN 的 FROM 子句中的子查询的语法