ORACLE,SELECT *来自2个标准,其中标准不匹配

时间:2014-12-10 18:24:27

标签: sql oracle not-exists

我们有一个定期运行并验证货件数据的批处理,然后将与错误有关的行转储到名为AN_VALIDATION_ERRORS表的表中。

第一次运行时,我可以获得看起来像这样的数据(生病做一个每个级别都有错误的例子):

error_seq | asn | po   | carton | upc  | error_code | error_origin | error_level
--------------------------------------------------------------------
  1       | 1   | null | null   | null | SO         | B            | S -- shipment
  2       | 1   | 90   | null   | null | NF         | B            | O -- order
  3       | 1   | 92   | 45     | null | SC         | B            | C -- carton
  4       | 1   | 92   | 45     | 567  | ST         | B            | I -- item

重新验证数据后,批处理只会将更多行转储到此表中,但不会清理旧行。但是,有一点不同,随后的时间,它会转储有error_origin =' S'。数据现在看起来像这样:

error_seq | asn | po   | carton | upc  | error_code | error_origin | error_level
--------------------------------------------------------------------
  1       | 1   | null | null   | null | SO         | B            | S -- shipment
  2       | 1   | 90   | null   | null | NF         | B            | O -- order
  3       | 1   | 92   | 45     | null | SC         | B            | C -- carton
  4       | 1   | 92   | 45     | 567  | ST         | B            | I -- item

  5       | 1   | 92   | 45     | null | SC         | S            | C -- new row

这意味着,所有未重新创建的行都被清除,并且持续存在的错误是错误原因为' S'。在我的示例中,error_seq 3和5是相同的错误,其余的被清除或修复。

我很容易通过选择error_origin =' S'来获取当前错误的列表。在一行有一个' S的情况下。但是,我还需要能够获得以前修复过的错误列表。在我的例子中,这将是error_seq {1,2,4}的行。

这是我试过的,这是错误的,但作为我尝试做什么的想法:

WITH B_LIST AS (

 SELECT *
 FROM ASN.AN_VALIDATION_ERRORS
 WHERE ERROR_ORIGIN = 'B'   
 AND INTERNAL_ASN = 1

)

, S_LIST AS (

-- ALL OPEN ERRORS
 SELECT *
 FROM ASN.AN_VALIDATION_ERRORS
 WHERE ERROR_ORIGIN = 'S'  
 AND INTERNAL_ASN = 1

)
, CLOSED_LIST AS (

 -- TRY TO GET ALL ROWS WITH ERROR_ORIGIN = 'B' WHERE A CORRESPONDING ROW OF ERROR_ORIGIN = 'S' DOES NOT EXIST
 SELECT *
 FROM B_LIST BL
 WHERE NOT EXISTS (
  SELECT * 
  FROM S_LIST SL
  WHERE SL.ORIG_PO_NO = BL.PO_NO
  AND SL.CARTON_NO = BL.CARTON_NO
  AND SL.UPC_NO = BL.UPC_NO
  AND SL.ERROR_CODE = BL.ERROR_CODE
 )
)

SELECT * FROM CLOSED_LIST;

此查询需要为我提供已修复的所有错误的列表,并以我的数据为例,结果必须是:

error_seq | asn | po   | carton | upc  | error_code | error_origin | error_level
--------------------------------------------------------------------
  1       | 1   | null | null   | null | SO         | B            | S -- shipment
  2       | 1   | 90   | null   | null | NF         | B            | O -- order
  4       | 1   | 92   | 45     | 567  | ST         | B            | I -- item

1 个答案:

答案 0 :(得分:2)

以前修复的错误是那些最近没有“S”的行。我对行之间的实际匹配条件有点不清楚,所以我猜它是asnerror_code

您可以使用not exists得到您想要的内容,如下所示:

select cl.*
from ASN.AN_VALIDATION_ERRORS ve
where error_origin = 'B' and
      not exists (select 1
                  from ASN.AN_VALIDATION_ERRORS ve2
                  where ve2.asn = ve.asn and
                        ve2.error_code = ve.error_code and
                        ve2.id > ve.id and
                        ve2.error_origin = 'S'
                 );

编辑:

有关匹配列的完整列表(也可以是NULL):

select cl.*
from ASN.AN_VALIDATION_ERRORS ve
where error_origin = 'B' and
      not exists (select 1
                  from ASN.AN_VALIDATION_ERRORS ve2
                  where ve2.asn = ve.asn and
                        ve2.error_code = ve.error_code and
                        (ve2.po = ve.po or ve2.po is null and ve.po is null) and
                        (ve2.carton = ve.carton or ve2.carton is null and ve.carton is null) and
                        (ve2.upc = ve.upc or ve2.upc is null and ve.upc is null) and
                        ve2.id > ve.id and
                        ve2.error_origin = 'S'
                 );