重叠记录

时间:2012-07-30 11:19:05

标签: sql database oracle10g

我有一个名为PRODUCTS的表,每个PRODUCT_NO_REGISTRATION_NO只允许使用一次产品开始日期,并且返回日期不应该发生冲突。

我们退回产品并在ACTUAL_RETURN_DATE中输入退货日期,如果ACTUAL_RETURN_DATE为空,我们将END_DATE作为退货日期。

您可以看到记录here

例如PRODUCT_NO_REGISTRATION_NO is clashing, as HP_2014 is returned on 18-Jun-2001, however HP_2012 same PRODUCT_NO_REGISTRATION_NO is allotted on 18-Jun-2001.

如何使用sql找出记录是否重叠?

更新1

PRODUCTS中有一项修改要包括PRODUCT_EXTENSION_NOPRODUCT_NO,PRODUCT_NO_REGISTRATION_NO and PRODUCT_EXTENSION_NO的组合成为唯一的行(复合主键)。

规则如下 每个PRODUCT_NO_REGISTRATION_NO仅允许在产品开始日期使用一次,并且返回日期不应发生冲突。

我们退回产品并在ACTUAL_RETURN_DATE中输入退货日期,如果ACTUAL_RETURN_DATE为空,我们将END_DATE作为退货日期。

PRODUCT_NO有扩展名,因此END_DATE已延长。

Sql Fiddle

E.g。如果你看到记录 PRODUCT_NO - ORP76PRODUCT_EXTENSION_NO - 1PRODUCT_NO - ORP100PRODUCT_EXTENSION_NO - 0发生冲突。

如何使用sql找出记录是否重叠,但允许PRODUCT_NO的扩展名。即扩展名为PRODUCT_NO的{​​{1}} ORP76和扩展名1基本上已扩展。

1 个答案:

答案 0 :(得分:1)

假设product_no是唯一的,您可以自行加入产品表并检查overlapping dates

select *
  from PRODUCTS
 inner join products products_test
    on products.PRODUCT_NO_REGISTRATION_NO 
     = products_test.PRODUCT_NO_REGISTRATION_NO
   and products.start_date 
    <= nvl (products_test.ACTUAL_RETURN_DATE, products_test.end_date)
   and nvl (products.ACTUAL_RETURN_DATE, products.end_date) 
    >= products_test.start_date
   and products.product_no 
    <> products_test.product_no

And here is Sql Fiddle

编辑:使用rowid的版本:

select *
  from PRODUCTS
 inner join products products_test
    on products.PRODUCT_NO_REGISTRATION_NO 
     = products_test.PRODUCT_NO_REGISTRATION_NO
   and products.start_date 
    <= nvl (products_test.ACTUAL_RETURN_DATE, products_test.end_date)
   and nvl (products.ACTUAL_RETURN_DATE, products.end_date) 
    >= products_test.start_date
   and products.rowid
    <> products_test.rowid

Second Sql Fiddle

澄清之后

更新:我们的想法是在extended条记录中获取产品开始日期和结束日期的最小和最大范围,然后比较两个流,以便范围重叠去除自引用通过测试product_no和product_no_registration_no。

with extended as
(
  select PRODUCT_NO, 
         PRODUCT_NO_REGISTRATION_NO, 
         min (START_DATE) as start_date,
         max (nvl (ACTUAL_RETURN_DATE, END_DATE)) as end_date
    from products
   group by PRODUCT_NO, PRODUCT_NO_REGISTRATION_NO
)
select e1.PRODUCT_NO_REGISTRATION_NO,
       e1.PRODUCT_NO,
       e1.start_date,
       e1.end_date,
       e2.PRODUCT_NO "PRODUCT_NO - CLASH",
       e2.start_date "START_DATE - CLASH",
       e2.end_date "END_DATE - CLASH"
  from extended e1
 inner join extended e2
    on e1.PRODUCT_NO_REGISTRATION_NO
     = e2.PRODUCT_NO_REGISTRATION_NO
   and e1.start_date <= e2.end_date
   and e1.end_date >= e2.start_date
-- Remove self-references
   and not
   (
           e1.PRODUCT_NO = e2.PRODUCT_NO
       and e1.PRODUCT_NO_REGISTRATION_NO 
         = e2.PRODUCT_NO_REGISTRATION_NO
   )

Third Sql Fiddle