我想知道如何在不必将此查询的主要部分写出(或使数据库处理过程)两次的情况下完成此操作。
我的情况是我正在查询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
的记录
答案 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
似乎是必要的。