2011-12-13 203 views
0

我被困在一个查询,需要您的帮助和suggestion.The的情况是:如何写这个查询

我有结构的表作为

JOB_ID,ITEM_ID,NEW_ITEM_ID,STATUS

其中,job_id是主键,状态可以是AC,SB。

现在我想写一个查询,只选择那些STATUS作为AC的表中没有ITEM_ID或NEW_ITEM_ID的行中状态为SB.I已经写了查询但它需要很多的时间,请您帮我写优化query.This我所写的

SELECT * FROM (
     SELECT JOB_ID,NEW_ITEM_ID,ITEM_ID,STATUS 
     FROM X1 
     WHERE STATUS='AC' 
     AND NEW_ITEM_ID IS NOT NULL 
     MINUS 
     (SELECT T1.JOB_ID,T1.NEW_ITEM_ID ,T1.ITEM_ID ,T1.STATUS 
     FROM (SELECT * 
       FROM X1 
       WHERE STATUS IN 'AC' 
       AND NEW_ITEM_ID IS NOT NULL ) T1 
     , (SELECT * 
      FROM X1 
      WHERE STATUS IN ('PR','SB') 
      AND NEW_ITEM_ID IS NOT NULL ) T2 
    WHERE (T2.ITEM_ID IN (T1.ITEM_ID,T1.NEW_ITEM_ID) 
        OR T2.NEW_ITEM_ID IN (T1.ITEM_ID,T1.NEW_ITEM_ID) 
     ) 
    AND T1.STATUS!=T2.STATUS 
    ) 
) T 

编辑

此表将包含数百万条记录30M左右说。

+2

你有忘了在标签中指定`firebird`和`db2` – zerkms 2011-12-13 19:56:56

+0

heh。@Algorithmist:你正在使用哪个DBMS? – 2011-12-13 19:57:54

+0

@Tomalak oracle 11g。 – Algorithmist 2011-12-13 20:01:37

回答

1

最简单的方法是将有选择所有ITEM_IDS和NEW_ITEM_IDs其状态为SB查询,则有另一种这样的查询:

SELECT * FROM table WHERE STATUS = 'AC' AND WHERE ITEM_ID NOT IN (the results of the previous query) AND WHERE NEW_ITEM_ID NOT IN (the results of the query for NEW_ITEM_IDs mentioned above)

只是一个想法,但有了正确的语法,我认为这应该工作。

0

试试这个:

select * from status where STATUS ='AC' or (STATUS ='SB' and ITEM_ID is null) or or (STATUS ='SB' and NEW_ITEM_ID is null) 
0

这听起来像你正在寻找(1)式中的地位是交行(2)没有其他排在ITEM_ID或new_item_id的比赛中,状态为SB ?

如何:

SELECT job_id, item_id, new_item_id, status 
    FROM x1 a 
WHERE a.status = 'AC' 
    AND NOT EXISTS (SELECT 1 FROM x1 b 
        WHERE b.status = 'SB' 
         AND (b.new_item_id = a.item_id 
          OR b.item_id = a.new_item_id) 
0

“此表将包含数百万条记录说周围30M”

这是一个关键部分的信息,但其他几个关键的统计信息缺失。 “PR”,“SB”和“AC”的状态有多少行? new_item_id填充了多少行?这些列是否被索引?

您在子查询中选择* from x1'。 SELECT *是不好的做法,一个等待发生的错误。然而,这是灾难性的,因为您不使用任何列,但是您迫使数据库读取结果集中每个条目的整个行。行越长,价格越高。在子查询中,如果你可能这样做,你真的应该开始索引索引。

理想情况下,您将在X1(STATUS,NEW_ITEM_ID,ITEM_ID,JOB_ID)上有一个索引。那么你根本不会碰到桌子。但至少你需要一个索引(STATUS,NEW_ITEM_ID)。 STATUS上的索引不会对你有任何好处,除非STATUS具有很高的选择性 - 数百个不同的值,均匀分布。 (这似乎不太可能:根据我的经验,大多数状态栏有几个不同的状态_。

您发布的查询命中了三次表X1;这需要很长时间,所以最主要的是减少点击次数表。这是子查询的保理可以帮助:

with data as ( select job_id, new_item_id, item_id, status 
       from x1 
       where status in ('PR','SB', 'AC') 
       and new_item_id is not null) 
select t1.* 
from data t1 
    , data t2 
where t1.status = 'AC' 
and t2.status in ('PR','SB') 
abd (t2.new_item_id in (t1.new_item_id, t1.item_id) 
    or t2.item_id in (t1.new_item_id, t1.item_id)) 
/

所以此查询打表一次,并且具有良好的索引一次也没有。

如果查询仍然需要太多时间 - 或者您不能缠绕有用的索引 - 用于改善对大量表执行时间的另一选项是并行查询。此选项是开放给你,如果你有一个企业版许可证,并有足够的CPU的服务器(如果要运行多万行的tables_应用程序数据库这两个条件应该是真实的。

with data as ( select /*+ parallel (x1, 4) */ 
         job_id, new_item_id, item_id, status 
       from x1 
       ...