在greenplum中查询优化

时间:2017-08-30 06:08:39

标签: sql greenplum

我有一个查询

SELECT ROW_NUMBER() OVER (ORDER BY getdate()) AS ID, GETDATE() as time, tmp.* from 
( select RecordType, TrnYear, SUM(MonthlySales) as AnnualSales
FROM vwKPI_SalesGraphMonthly
WHERE RecordType = 'A'
GROUP BY RecordType, TrnYear

UNION ALL

SELECT RecordType, TrnYear, SUM(MonthlySales) as AnnualSales
FROM vwKPI_SalesGraphMonthly
WHERE RecordType = 'B'
GROUP BY RecordType, TrnYear

UNION ALL

SELECT RecordType, TrnYear, SUM(MonthlySales) as AnnualSales
FROM vwKPI_SalesGraphMonthly
WHERE RecordType = 'R'
GROUP BY RecordType, TrnYear

UNION ALL

SELECT 'Y', TrnYear, SUM(MonthlySales) as AnnualSales
FROM vwKPI_SalesGraphMonthly CROSS JOIN ArControl  
25 THEN FinPeriod -1 ELSE FinPeriod END)
WHERE RecordType = 'B' AND TrnMonth <=DATE_PART('month', GETDATE())
GROUP BY RecordType, TrnYear
) tmp

vwKPI_SalesGraphMonthly是大约300行的另一个查询。 我不想在此查询中插入vwKPI_SalesGraphMonthly 4次的定义。有没有办法在查询中只声明一次vwKPI_SalesGraphMonthly的定义,并在所有联合中使用它。

1 个答案:

答案 0 :(得分:0)

是的,CTE适用于set optimizer=on

Pivotal Query Optimizer处理包含WITH子句的查询。 WITH子句(也称为公用表表达式(CTE))生成仅为查询存在的临时表。此示例查询包含CTE。

WITH v AS (SELECT a, sum(b) as s FROM T where c < 10 GROUP BY a)
  SELECT *FROM  v AS v1 ,  v AS v2
  WHERE v1.a <> v2.a AND v1.s < v2.s;

作为查询优化的一部分,Pivotal Query Optimizer可以将谓词下推到CTE中。例如,查询,Pivotal Query Optimizer将等式谓词推送到CTE。

WITH v AS (SELECT a, sum(b) as s FROM T GROUP BY a)
  SELECT *
  FROM v as v1, v as v2, v as v3
  WHERE v1.a < v2.a
    AND v1.s < v3.s
    AND v1.a = 10
    AND v2.a = 20
    AND v3.a = 30;

Pivotal Query Optimizer可以处理这些类型的CTE: 定义一个或多个表的CTE。在此查询中,CTE定义了两个表。

WITH cte1 AS (SELECT a, sum(b) as s FROM T 
               where c < 10 GROUP BY a),
      cte2 AS (SELECT a, s FROM cte1 where s > 1000)
  SELECT *
  FROM cte1 as v1, cte2 as v2, cte2 as v3
  WHERE v1.a < v2.a AND v1.s < v3.s;
Nested CTEs.
WITH v AS (WITH w AS (SELECT a, b FROM foo 
                      WHERE b < 5) 
           SELECT w1.a, w2.b 
           FROM w AS w1, w AS w2 
           WHERE w1.a = w2.a AND w1.a > 2)
  SELECT v1.a, v2.a, v2.b
  FROM v as v1, v as v2
  WHERE v1.a < v2.a;