重叠数据(Overlapping Data)

2019-10-17 06:27发布

我有一个SQL查询表产品,以检查产品记录重叠。 在大多数情况下,查询工作,除了以下的罚款。

select * from products where 
product_reg_no = 'AL-NAPT' 
and (to_date('14-Aug-2001') BETWEEN to_date('27-Aug-2001') AND to_date('30-Aug-2001')
or to_date('31-Aug-2001') BETWEEN to_date('27-Aug-2001') AND to_date('30-Aug-2001'))

如何使这个查询来捕获所有记录都重叠的部分或全部?

如果需要,我可以提供样品记录表结构。

谢谢

更新1

我已经加入表结构和记录这里或如下:

create table products
(product_reg_no varchar2(32),
 start_date date,
 end_date date);


Insert into products
   (product_reg_no, START_DATE, END_DATE)
 Values
   ('AL-NAPT', TO_DATE('08/14/2012', 'MM/DD/YYYY'), TO_DATE('08/31/2012', 'MM/DD/YYYY'));
Insert into products
   (product_reg_no, START_DATE, END_DATE)
 Values
   ('AL-NAPT', TO_DATE('08/27/2012', 'MM/DD/YYYY'), TO_DATE('08/30/2012', 'MM/DD/YYYY'));
COMMIT;

的第一个记录是从14 2012年8月,8 月,31 2012是与从八月第二记录,27 20128月,30 2012重叠。 所以,我怎么能修改我的查询来获取重叠?

Answer 1:

请参见确定两个日期范围是否重叠 。

您需要评估以下,或使用就可以了轻微变异<=而非< ,也许是:

Start1 < End2 AND Start2 < End1

既然你有一个表的工作,你需要有一个自联接:

SELECT p1.*, p2.*
  FROM products p1
  JOIN products p2
    ON p1.product_reg_no != p2.product_reg_no
   AND p1.start < p2.end
   AND p2.start < p1.end;

在不相等条件确保你没有得到与自己配对(虽然创纪录的<条件也保证了,但如果你使用<=在不相等的条件将是一个不错的主意。

这将产生两行用于每个对产品(一行与产品A为p1和产品B作为p2 ,其他与产品B为p1和产品A为p2 )。 为了防止这种情况发生,改变!=为任何<>


而且,在样本数据更密切关注,它可能是你在注册号匹配和日期重叠的几行真的很有趣。 在这种情况下,你可以忽略我对威特灵!=<> ,取而代之的条件=毕竟。

SELECT p1.*, p2.*
  FROM products p1
  JOIN products p2
    ON p1.product_reg_no = p2.product_reg_no
   AND p1.start < p2.end
   AND p2.start < p1.end;

SQL小提琴(未保存的)表明,这种工作原理:

SELECT p1.product_reg_no p1_reg, p1.start_date p1_start, p1.end_date p1_end,
       p2.product_reg_no p2_reg, p2.start_date p2_start, p2.end_date p2_end
  FROM products p1
  JOIN products p2
    ON p1.product_reg_no = p2.product_reg_no
   AND p1.start_date < p2.end_date
   AND p2.start_date < p1.end_date
 WHERE (p1.start_date != p2.start_date OR p1.end_date != p2.end_date);

WHERE子句消除了被连接到自己的行。 在SELECT列表中的重复的列名淘汰了,你能看到所有数据。 我加了一行:

INSERT INTO products (product_reg_no, start_date, end_date)
VALUES ('AL-NAPT', TO_DATE('08/27/2011', 'MM/DD/YYYY'), TO_DATE('08/30/2011', 'MM/DD/YYYY'));

这是没有选择的 - 证明,它并拒绝不重叠的条目。

如果你想消除双行,那么你必须添加其他花哨的标准:

SELECT p1.product_reg_no p1_reg, p1.start_date p1_start, p1.end_date p1_end,
       p2.product_reg_no p2_reg, p2.start_date p2_start, p2.end_date p2_end
  FROM products p1
  JOIN products p2
    ON p1.product_reg_no = p2.product_reg_no
   AND p1.start_date < p2.end_date
   AND p2.start_date < p1.end_date
 WHERE (p1.start_date != p2.start_date OR p1.end_date != p2.end_date)
   AND (p1.start_date < p2.start_date OR
       (p1.start_date = p2.start_date AND p1.end_date < p2.end_date));


Answer 2:

这是一个奇怪的查询。 您是否08月14日 - 2001年是27月 - 2001年30月 - 2001年这始终是虚假或8月31日 - 2001年是27月 - 2001年30月 - 2001年也一直是假之间。 所以,你where条款将永远是假的。

编辑:谢谢你澄清

SQL小提琴演示

select   p1.product_reg_no
       , p1.start_date p1s
       , p1.end_date   p1e
       , p2.start_date p2s
       , p2.end_date   p2e
from products p1, products p2
where p1.product_reg_no = p2.product_reg_no
  and not (    p1.end_date   < p2.start_date
           and p1.start_date > p2.end_date   );

你想要的是以下情况中(1个代表第一行2第二)

1    1
 2  2

 1  1
2    2

1    1
2    2

1   1
 2   2

 1   1
2   2

那你也可以转过身,说你不想要这个:

1 1
   2 2

   1 1
2 2

我以为你也需要这么做

1 1
  2 2

  1 1
2 2

WHERE子句也可以写不同

not (    p1.end_date   < p2.start_date and p1.start_date > p2.end_date   )

是相同的

        p1.end_date   >= p2.start_date or p1.start_date <= p2.end_date   

我认为这是所谓德·摩根定律,当我亿万年前曾在学校。

你可能必须考虑,如果你有2级以上的行会发生什么。



文章来源: Overlapping Data