1

I have a table called PRODUCTS and each PRODUCT_NO_REGISTRATION_NO is allowed to be used only once that is product start date and return date should not clashing.

We return the products and return date is entered in ACTUAL_RETURN_DATE and if ACTUAL_RETURN_DATE is null we take END_DATE as return date.

You could see the records here

For example 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.

How can I find out using sql whether records are overlapping?

Update 1

There was a modification in table PRODUCTS to include PRODUCT_EXTENSION_NO. Combination of PRODUCT_NO,PRODUCT_NO_REGISTRATION_NO and PRODUCT_EXTENSION_NO becomes a unique row (composite primary key).

Rules are as below Each PRODUCT_NO_REGISTRATION_NO is allowed to be used only once that is product start date and return date should not clashing.

We return the products and return date is entered in ACTUAL_RETURN_DATE and if ACTUAL_RETURN_DATE is null we take END_DATE as return date.

PRODUCT_NO has extensions, so the END_DATE is extended.

Sql Fiddle

E.g. if you see the records PRODUCT_NO - ORP76 with PRODUCT_EXTENSION_NO - 1 is clashing with PRODUCT_NO- ORP100 with PRODUCT_EXTENSION_NO - 0.

How can I find out using sql whether records are overlapping, extension of PRODUCT_NO is allowed though. i.e. PRODUCT_NO ORP76 with extension 0 and extension 1 are basically extended.

Jacob
  • 14,463
  • 65
  • 207
  • 320

1 Answers1

1

Assuming that product_no is unique, you might self-join products table and check for 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.

EDIT: a version using 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

UPDATE after clarification: the idea is to get minimum and maximum range of product start and end date counting in extended records, and then compare two streams for range overlap removing self-references by testing product_no and 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.

Community
  • 1
  • 1
Nikola Markovinović
  • 18,963
  • 5
  • 46
  • 51
  • There could be instances that product_no are not unique. Thanks – Jacob Jul 30 '12 at 11:59
  • @Polappan There must be a way to exclude a record from matching itself. You might use rowid to that effect ... – Nikola Markovinović Jul 30 '12 at 12:05
  • I will test this thoroughly as I how it is working and will get back to you. Thanks a lot Nikola. – Jacob Jul 30 '12 at 12:18
  • I have modified table structure and added rules above as update 1. How can I get overlapping or clashing records? Thanks. – Jacob Aug 06 '12 at 06:50
  • @Polappan I'm sorry, I don't understand the business with `PRODUCT_NO \ PRODUCT_EXTENSION_NO`. How is END_DATE extended? What does it mean `extension of product_no is allowed`? – Nikola Markovinović Aug 06 '12 at 08:28
  • If user wants to extend `PRODUCT_NO_REGISTRATION_NO`, they extend the `END_DATE` by adding another record with `PRODUCT_EXTENSION_NO` as `1` (previous record is `0`). So `PRODUCT_NO` remains the same along with `PRODUCT_NO_REGISTRATION_NO`, only extension will be in sequence like `0,1,2` etc. I hope I made it clear, other kindly let me know. Thanks and appreciated. – Jacob Aug 06 '12 at 08:40
  • @Polappan I'm sorry for the delay, I've been reluctant to try to understand the problem. I hope that this arrives on time though. – Nikola Markovinović Aug 07 '12 at 10:32
  • Thanks Nikola for your time and valuable input. I am testing this to see it is catching clashing records, Appreciated. Regards. – Jacob Aug 09 '12 at 05:22
  • I tried to remove the `with extended as` from the query but was not successful. Is it possible to remove the `with extended as` from the query? Regards. – Jacob Aug 09 '12 at 11:11
  • No, not without complete rewrite. Why would you want to remove it? You don't want to treat all extensions as one record? – Nikola Markovinović Aug 09 '12 at 11:15
  • No need to rewrite I will manage with this. I am still testing the results. Thanks again. Regards – Jacob Aug 09 '12 at 12:29