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 JOIN
s 的内容都会更难阅读。
【讨论】:
更具体地说,查询计划器可以并且经常做扁平化子查询,将条件从子查询拉到外部查询,将条件从外部查询推送到子查询等。子查询大多只是符号,并且与查询的实际执行方式没有您想象的那么大的关系。至少在 PostgreSQL 中。【参考方案2】:优势
子查询是有利的,因为它们构造查询以隔离语句的每个部分,执行通常需要复杂连接和联合的相同操作并且更易于阅读。缺点
使用子查询时,查询优化器可能需要执行额外的步骤,因此它们的执行时间比连接要长。
对父查询的每一行执行一次不相关的子查询。如果这种子查询处理大量数据,您应该预计处理数据需要很长时间。
可能的解决方案:
您可以创建临时表来存储子查询的数据,然后使用 JOIN 来完成查询。请记住,使用 JOIN 比使用子查询更好。 How to Create a Table
使用 with 子句。 WITH
提供了一种编写辅助语句以用于更大查询的方法。这些语句,通常被称为公用表表达式或 CTE,可以被认为是定义仅用于一个查询的临时表。它允许您只执行一次子查询,而不是为每一行执行它。 How to Use With Clause
注意:您应该避免使用 UNION 或 UNION ALL。
【讨论】:
你的缺点不正确。相关子查询对外部查询中的每一行执行一次,但不相关子查询不会。临时表通常较慢且不必要,因为您可以使用 CTE,由于优化器防护也存在问题。这确实不准确。就此而言,优势部分也不正确,因为优化器可以拉起、下推和展平子查询。以上是关于Psql - from 子句中的子查询 - 不好的做法?的主要内容,如果未能解决你的问题,请参考以下文章
使用 FROM 子句中的子查询进行联接操作中的 SQL 语法错误
带有联合错误的 MySQL 视图 - “视图的 SELECT 包含 FROM 子句中的子查询”