Oracle - 比较同一数据库中的两个类似表

时间:2017-03-28 22:18:41

标签: oracle oracle11g

我在同一个oracle数据库中有两个表PROD_DEMOPROD_IMP。两者都具有相同的结构和约束。两个表都有一个主键PROD_CODE

我必须显示PROD_IMP表中的所有记录,其中一个添加列STATUS显示记录是否已更新或添加到PROD_IMP表中。

我已经写了下面的查询来实现这一目标,但我确信这需要一些改进才能使它更快。

select imp.*, decode(c.record_count, 2, 'U', 1, 'A', null) from prod_imp imp
left join
    (Select prod_code, count(1) as record_count from
        (
            (SELECT * FROM prod_demo UNION SELECT * FROM prod_imp)
            MINUS 
            (SELECT * FROM prod_demo INTERSECT SELECT * FROM prod_imp)

        ) group by prod_code) c 
on imp.prod_code = c.prod_code;

我知道这个查询还会列出从PROD_DEMO表中删除的记录,但在我的情况下不会发生。

执行计划如下所示:

enter image description here

两个表都可以有数千条记录。现在我的问题是如何改善此查询的性能。

2 个答案:

答案 0 :(得分:0)

我假设如果记录存在于prod_demo中但不存在于prod_imp中,则会添加该记录。如果两者都存在,并且任何字段已更改,则更新。下面的查询可能会也可能不会提高性能,具体取决于表的大小和匹配记录的数量。具有union,interest和minus的内部选择要求多次检查两个表中每个记录的每个字段,并且不能利用任何索引。下面的示例尝试通过仅比较两个表中存在的记录中的所有字段来最小化完整记录比较的数量。

-- Inserts
select d.*, 'A' [status]
from prod_demo d
left join prod_imp i on d.prod_code=i.prod_code
where i.prod_code is null

union

-- Updates
select d.*, 'U' [status]
from prod_demo d
join
(
    select prod_demo.prod_code,count(1)
    from
    (
        select prod_imp.*
        from prod_imp
        join prod_demo on prod_imp.prod_code=prod_demo.prod_code
        union
        select prod_demo.*
        from prod_demo 
        join prod_imp on prod_imp.prod_code=prod_demo.prod_code

    ) matches
    group by prod_demo.prod_code
    having count(1) > 1
) updates on d.prod_code = updates.prod_code

答案 1 :(得分:0)

直接的方法是从prod_demo中选择(因为需要显示其所有记录)并查找select i.*, case when d.prod_code is null then 'added' when decode(i.col1, d.col1, 0, 1) = 1 or decode(i.col2, d.col2, 0, 1) = 1 or ... then 'updated' else 'unaltered' end as status from prod_imp i left join prod_demo d on d.prod_code = i.prod_code; 以确定每条记录的状态:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="2.0">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <!-- identity transform template with mode='olr' -->
    <xsl:template match="@* | node()" mode="olr">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()[1]" mode="olr"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]" mode="olr"/>
    </xsl:template>

    <!-- identity transform template -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()[1]"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>

    <!-- copy the olr and it's following-elements in the current element -->
    <xsl:template match="wrapper/item[descendant::olr]">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()[1]" />
        </xsl:copy>
        <xsl:apply-templates select="descendant::olr[not(preceding-sibling::olr)]" mode="olr"/>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>

    <!-- "do nothing for olr" template -->
    <xsl:template match="olr[ancestor::item/parent::wrapper]"/>

</xsl:stylesheet>

这应该尽可能快。