我可以别名并重用我的子查询吗?

时间:2017-01-17 19:47:53

标签: sql postgresql

我正在使用数据仓库来生成报告。顾名思义,我有很多数据。其中一个提取大量数据的查询花费的时间比我想要的要长(这些查询不是临时执行的,这些查询每晚运行并重建表来缓存报告)。

我正在考虑优化它,但我对我能做的事情有点限制。我有一个问题是按照......

编写的
SELECT column1, column2,... columnN, (subQuery1), (subquery2)... and so on.

问题是,子查询重复了相当多,因为每个语句都有一个例子,例如......

SELECT
    column1
    , column2
    , columnN
    , (SELECT 
        CASE
            WHEN (subQuery1) > 0 AND (subquery2) > 0 
            THEN CAST((subQuery1)/(subquery2) AS decimal)*100
            ELSE 0 
        END) AS "longWastefulQueryResults"

我们的数据来自多个来源,并且偶尔会出现数据输入错误,因此可以防止在除以零时出现潜在错误。问题是,即使值不会改变,子查询也可以重复多次。我确信有更好的方法来做到这一点......

我喜欢你在下面看到的内容,但是我在group by子句中遇到了需要sq1和sq2的错误。我会提供一个精确的样本,但过去是非常繁琐的。

SELECT
    column1
    , column2
    , columnN
    , (subQuery1) as sq1
    , (subquery2) as sq2
    , (SELECT 
        CASE
            WHEN (sq1) > 0 AND (sq2) > 0 
                THEN CAST((sq1)/(sq2) AS decimal)*100
            ELSE 0 
        END) AS "lessWastefulQueryResults"

我正在使用Postgres 9.3但尚未成功通过测试。我可以做些什么来优化我的查询?

3 个答案:

答案 0 :(得分:0)

是的,您可以创建Temp Table来存储结果并在同一会话中再次查询

答案 1 :(得分:0)

列列表中的子查询往往是一个有问题的设计。我解决此问题的第一种方法是看你是否可以将它们移到std::map<>条款。

除了允许您在多列中使用这些查询的结果之外,执行此操作通常还有助于优化程序为您的查询提供更好的计划。这是因为列列表中的查询必须为每一行执行,而不是合并到结果集的其余部分。

由于您在问题中仅包含了部分查询,因此我无法证明这一点,但您应该寻找的内容更像是:

from

答案 2 :(得分:0)

我不确定Postgres优化器有多好,所以我不确定以这种方式优化是否会带来任何好处。 (在我看来,它不应该是因为DBMS应该照顾这种事情;但如果它不是,那就不足为奇了。)OTOH如果你现在的形式有你重复查询逻辑,然后你可以从做一些不同的事情中受益,无论它是否有助于提高性能......

您可以将子查询放在with子句中,这可能会有所帮助。

  with subauery1 as (select ...)
     , subquery2 as (select ...)
select ...

这类似于将子查询放在FROM子句中,正如艾伦建议的那样,但如果您的查询很复杂,可能会提供更大的灵活性。

如果你可以像安德鲁所暗示的那样自由创建临时表,那也可以起作用但可能是一把双刃剑。此时,您通过坚持首先填充临时表然后以对您有意义的方式使用来限制优化程序的选项,这可能并不总是实际上获得最高效率的方式。 (再说一次,这取决于优化器有多好......试图超越一个非常好的那个经常是愚蠢的。)另一方面,如果你创建临时表或工作表,你可能会应用有用的索引或统计数据(如果它们包含大型数据集),这将进一步改善下游步骤&#39;性能

看起来您的许多子查询可能会返回单个值。您可以将查询放入过程并将这些单个值捕获为变量。这类似于临时表方法,但不需要创建对象(因为您可能无法做到这一点),并且通过让它担心表格中的#39来降低优化程序的混淆风险较小。 ; s真的只是一个价值。