sql - 重叠数据

标签 sql database oracle10g

我有一个 sql 查询来检查表 PRODUCTS 中产品记录的重叠。 在大多数情况下,查询工作正常,但以下情况除外。

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

我添加了表结构和记录here或者如下:

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;

2012年8月14日2012年8月31日的第一条记录与 第二个记录是从2012年8月27日2012年8月30日。那么如何修改我的查询以获得重叠?

最佳答案

参见 Determine whether two date ranges overlap .

您需要使用 <= 评估以下内容或它的次要变体而不是 < ,也许:

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;

不相等的条件确保您不会获得与其自身配对的记录(虽然 < 条件也确保了这一点,但如果您使用了 <=,不相等的条件将是一个好主意。

这将为每对产品生成两行(一行 ProductA 为 p1 和 ProductB 为 p2 ,另一行 ProductB 为 p1 和 ProductA 为 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 Fiddle(未保存)表明这是可行的:

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));

关于sql - 重叠数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12667726/

相关文章:

c# - 是否可以停止执行 sql 查询?

SQL - 更新查询只更新一个字段

mysql - Mysql 中的自连接

mysql - SQL:如何总结几十年的计数?

mysql - SQL:简化多列上的 and,or 查询

c# - 通过代码添加 Entity Framework 迁移

php - Laravel 5.2 更新数据库表

oracle - 每组最大的行 - 进一步将结果集与左连接与 Hibernate 中的其他相关表相结合 - HQL。是否可以?

php - mysql_fetch_assoc() 的 PDO 方法?

database - 如何创建Oracle数据库的dmp文件?