代码之家  ›  专栏  ›  技术社区  ›  Omnipresent

比较oracle中的两个游标而不是使用减号

  •  0
  • Omnipresent  · 技术社区  · 16 年前

    由于表包含大量数据,因此运行以下查询需要3分钟以上:

      SELECT  RTRIM(LTRIM(A.HEAD)),
          A.EFFECTIVE_DATE,
        FROM   TABLE_1 A
        WHERE  A.TYPE_OF_ACTION='6'
        AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)  
    
        MINUS
    
        SELECT  RTRIM(LTRIM(B.head)),
          B.EFFECTIVE_DATE,
        FROM  TABLE_2 B
    

    在我们的系统中,如果查询运行超过8秒,它就会被终止。有没有一种方法可以分别运行查询,把它们放进游标,比较然后得到结果?这样,每个查询将单独运行,而不是作为一个需要3分钟的大规模查询运行。

    如何比较两个游标来模拟 MINUS

    2 回复  |  直到 16 年前
        1
  •  1
  •   Gary Myers    16 年前

    减号是一个集合操作,它除了将第二个查询的结果从第一个查询中移除外,还将删除第一个集合中出现的重复项。 因此,所显示的查询在返回给用户之前,必须从表1构建完整的结果集。

    如果您可以确定第一组中没有trimemd head/effective date的重复项(或者您不希望删除这些重复项),您可以尝试

    SELECT  RTRIM(LTRIM(A.HEAD)), A.EFFECTIVE_DATE,
        FROM   TABLE_1 A
        WHERE  A.TYPE_OF_ACTION='6'
        AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)
        AND NOT EXISTS 
             (select 1 from table_2 b 
              where RTRIM(LTRIM(b.head)) = RTRIM(LTRIM(a.head))
              and b.effective_date = a.effective_date) )
    

    这样,查询可以更快地返回结果,特别是当表2非常小或者可以通过有效日期或标题上的索引访问行时。

    如果可以,删除RTRIM(LTRIM())位。

    PPS公司。仍然不能保证它会在8秒内返回。这将取决于表\u1的大小,以及对\u操作类型和/或有效日期的索引。

    补充:

    SELECT  RTRIM(LTRIM(A.HEAD)), A.EFFECTIVE_DATE,
        FROM   TABLE_1 A
        WHERE  A.TYPE_OF_ACTION='6'
        AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)
    

    如果返回则忽略行

        select 1 from table_2 b 
          where RTRIM(LTRIM(b.head)) = :1
          and b.effective_date = :1
          and rownum =1
    

    但完全执行肯定需要更长的时间。可能数量级更长(即小时),取决于每个表2检查需要多长时间。不完全确定截断使用的条件(调用的持续时间或打开SQL游标的持续时间),因此它可能会关闭外部游标。根据表1的大小/索引/内容,外部游标可能仍然不会在时间范围内返回第一行。

        2
  •  0
  •   Roy Tang    16 年前

    减号与“获取第一个查询的所有行,然后从该集合中删除第二个查询中的行”相同,因此您可以将第一个查询的结果加载到内存中的一个数组中,然后遍历第二个查询结果,并根据第一个查询结果逐个检查它们,如果它们存在,则将其删除。

    SELECT  RTRIM(LTRIM(A.HEAD)),
      A.EFFECTIVE_DATE,
    FROM   TABLE_1 A
    WHERE  A.TYPE_OF_ACTION='6'
    AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)  
    AND NOT EXISTS (
      SELECT 1 fFROM TABLE_2 B
      WHERE RTRIM(LTRIM(A.HEAD)) = RTRIM(LTRIM(B.HEAD))
      AND A.EFFECTIVE_DATE = B.EFFECTIVE_DATE
    )
    

    在RTRIM(LTRIM(A.HEAD))上可能还需要一些功能索引