使用相同的数据使Oracle UNION查询的效率提高两倍

时间:2013-02-21 14:48:04

标签: sql oracle

我想知道如何在不必将此查询的主要部分写出(或使数据库处理过程)两次的情况下完成此操作。

我的情况是我正在查询Oracle企业数据库(我受到DBA的限制,所以有些解决方案可能无法正常工作,但我不确定在有多大程度上我会受到限制,直到我尝试并且不知道还有什么地方。)

目前,我的查询如下:

    SELECT
        a.Field1,
        a.Field2,
        b.Field3,
        b.Field4,
        c.Field5
    FROM
        a,
        b,
        c,
    WHERE
            a.FieldX = b.FieldX
        AND
            b.FieldY = c.FieldY

UNION
  (
    SELECT
        d.Field6 as Field1,
        d.Field7 + d.Field8 as Field2,
        MainQuery.Field3,
        MainQuery.Field4,
        MainQuery.Field5
    FROM
        (
            SELECT
                a.Field1,
                a.Field2,
                b.Field3,
                b.Field4,
                c.Field5
            FROM
                a,
                b,
                c,
            WHERE
                    a.FieldX = b.FieldX
                AND
                    b.FieldY = c.FieldY
                AND
                    a.FieldZ = 'XXXX'
        ) MainQuery,

        d
    WHERE
        MainQuery.Field1 = d.Field6
  )

简单地说,我有一个主要查询(第一部分),它返回我的大部分结果,然后我重复主查询,带有额外的限制(a.FieldZ = 'XXXX')并从此查询中提取数据AND第二个表,并使用UNION将其附加到主查询。

我面临的主要挑战是Field1&的定义。 Field2在两个查询之间进行了更改,因此我无法弄清楚如何进行简单的连接。但我确信必须有一种方法可以实现这一点,而无需使数据库查询两次相同的数据。

有关如何提高此查询效率的任何想法吗?

谢谢!


根据评论,解释一下这个查询的更多内容 - 我要做的是在查询的前半部分获取我的整个数据,然后在查询的后半部分追加额外的行对于a.FieldZ = 'XXXX'Field1

的计算略有不同的Field2的记录

4 个答案:

答案 0 :(得分:2)

因此,根据您的意见,您的要求似乎是“第2列将从表格M中获取。另外,当M.fieldZ = 'XXX'需要来自表D的字段的额外行时需要添加。“

在这种情况下,您必须使用UNION ALL或通过连接到2行表来复制您的记录。您可以使用WITH子句在SELECT中重用子查询。这将使其更具可读性,优化器可能决定仅运行一次查询(通过将子查询的结果保存在temp中)。

WITH mainquery AS (SELECT /* your main query */)
SELECT *
  FROM mainquery
 UNION ALL
SELECT field1, d.field2 /*, ... */
  FROM (SELECT * FROM mainquery WHERE fieldZ = 'XXX') m
  JOIN d ON m.field1 = d.field6

答案 1 :(得分:1)

我认为这是一种方法,可以为您提供所需的答案。没有大量的数据,我无法判断它是否会更快。在这里,您将扫描临时表几次,但如果基本查询从表a,b,c和d返回一小组数据,那么可能会少工作。

with foo as 
   (SELECT
        a.Field1,
        a.Field2,
        a.FieldZ,
        b.Field3,
        b.Field4,
        c.Field5
    FROM
        a,
        b,
        c
    WHERE
            a.FieldX = b.FieldX
        AND
            b.FieldY = c.FieldY
)
select Field1
       ,field2
       ,field3
       ,field4
       ,field5 
from foo
union
select
 d.Field6 as Field1
 ,d.Field7 ||'+'|| d.Field8 as Field2
 ,foo.Field3
 ,foo.Field4
 ,foo.Field5
from foo
join d on foo.field1 = d.field6
where foo.fieldz = 'XXXX'

答案 2 :(得分:0)

使用case语句(http://www.techonthenet.com/oracle/functions/case.php

e.g。

select case when FieldZ = 'XXXX' then Field6 else Field1 end as Field1,
       case when FieldZ = 'XXXX' then Field7 + Field8 else Field2 as Field2,
       Field3,
       Field4,
       Field5
from   a join b on a.FieldX = b.FieldX
       join c on b.FieldY = c.FieldY
       left join d on a.Field1 = d.Field6

答案 3 :(得分:0)

如果您打算复制XXXX记录,那么您可以使用case语句将查询简化为适当的连接:

SELECT (case when a.FieldZ = 'XXXX' then a.Field1 else d.Field6 end) as Field1,
       (case when a.FieldZ = 'XXXX' then a.Field2 else d.Field7 + d.Field8 end) as Field2,
        b.Field3,
        b.Field4,
        c.Field5
FROM a join
     b
     on a.FieldX = b.FieldX join
     C
     on b.FieldY = c.FieldY left outer join
     d
     on A.Field1 = d.Field6 and
        a.FieldZ = 'XXXX'

如果您要复制这些记录,那么某些union all似乎是必要的。