2015-11-03 158 views
2

手头的任务是选择音乐家(pid)和每个乐器的数量,包括乐器只能在音乐会上演奏 - 这些乐器可能不在[播放]表格中。Psql - 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的任何内容将更难以阅读。

+1

更具体地说,查询规划器可以并且通常会扁平化子查询,将条件从子查询拉到外部查询,将条件从外部查询推入子查询等等。子查询大多只是符号化,并且不会与查询真正按照您的预期执行的方式一样多。至少在PostgreSQL中。 –

0

优势

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

缺点

  • 当使用子查询的查询优化可能需要因此他们需要更长的时间比加入执行执行额外的步骤。

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

可能的解决办法:

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

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

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

+0

你的缺点是不正确的。相关的子查询对外部查询中的每一行执行一次,但不相关的子查询则不执行。临时表通常比较慢,并且不必要,因为您可以使用CTE,这也存在由于优化器隔离导致的问题。这确实不准确。优势部分也是不正确的,因为优化器可以拉起,压下和扁平化子查询。 –

+0

你是对的...我编辑了答案。谢谢... –