Psql - 来自子句的子查询 - 不好的做法?

时间:2015-11-03 01:26:37

标签: select count psql union-all

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

我已经解决了它,但我读到如果可能的话,应该避免使用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;

2 个答案:

答案 0 :(得分:1)

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

如果您认为查询有问题,您可以随时启动psql的EXPLAIN ANALYZE功能。这将为您提供查询实际执行的操作的概述。这样,您还可以比较编写查询的不同方法。

你给出的例子......我认为你不能在没有子查询的情况下解决这个问题。我认为你选择的方式很好。涉及某些LEFT JOIN的任何内容都将更难以阅读。

答案 1 :(得分:0)

<强>优点

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

<强>缺点

  • 使用子查询时,查询优化器可能需要执行其他步骤,因此执行时间比连接要长。

  • 对于父查询的每一行,执行一次不相关的子查询。如果这种子查询处理大量数据,您应该会花费很长时间来处理数据。

可能的解决方案:

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

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

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