【问题标题】:Select where number range does not overlap选择数字范围不重叠的位置
【发布时间】:2019-01-14 17:27:57
【问题描述】:

我有两个表,其中包含有关道路建设活动的记录:

  • table_a 是主列表。
  • table_b 是旧列表。

对于每条道路,每年,我想从table_b中选择table_a中尚不存在的记录。

此外,记录应不沿道路在空间上重叠。更具体地说,table_b 中记录的from_m 和to_m 不应与table_a 中的from_m 和to_m 重叠。

我该怎么做?我没有 Oracle Spatial。


Excel 中的数据(方便查看):

这是数据在 Excel 中的样子:

绿色中的记录应该被查询选中; 红色中的记录不应该。


DDL:

表 A:

  create table table_a 
   (
    id number(4,0), 
    road_id number(4,0), 
    year number(4,0), 
    from_m number(4,0), 
    to_m number(4,0)
   );

insert into table_a (id,road_id,year,from_m,to_m) values (1,1,2000,0,100);
insert into table_a (id,road_id,year,from_m,to_m) values (2,1,2005,0,25);
insert into table_a (id,road_id,year,from_m,to_m) values (3,1,2005,50,75);
insert into table_a (id,road_id,year,from_m,to_m) values (4,1,2005,75,100);
insert into table_a (id,road_id,year,from_m,to_m) values (5,1,2010,10,50);
insert into table_a (id,road_id,year,from_m,to_m) values (6,1,2010,50,90);
insert into table_a (id,road_id,year,from_m,to_m) values (7,1,2015,40,100);
insert into table_a (id,road_id,year,from_m,to_m) values (8,2,2020,0,40);
insert into table_a (id,road_id,year,from_m,to_m) values (9,2,2020,0,40);
insert into table_a (id,road_id,year,from_m,to_m) values (10,3,2025,90,150);
commit;

select * from table_a;

        ID    ROAD_ID       YEAR     FROM_M       TO_M
---------- ---------- ---------- ---------- ----------
         1          1       2000          0        100
         2          1       2005          0         25
         3          1       2005         50         75
         4          1       2005         75        100
         5          1       2010         10         50
         6          1       2010         50         90
         7          1       2015         40        100
         8          2       2020          0         40
         9          2       2020          0         40
        10          3       2025         90        150

表 B:

  create table table_b 
   (
   id number(4,0), 
    road_id number(4,0), 
    year number(4,0), 
    from_m number(4,0), 
    to_m number(4,0)
   );

insert into table_b (id,road_id,year,from_m,to_m) values (1,1,1995,0,100);
insert into table_b (id,road_id,year,from_m,to_m) values (2,1,2001,0,50);
insert into table_b (id,road_id,year,from_m,to_m) values (3,1,2005,20,80);
insert into table_b (id,road_id,year,from_m,to_m) values (4,1,2005,0,100);
insert into table_b (id,road_id,year,from_m,to_m) values (5,1,2010,0,10);
insert into table_b (id,road_id,year,from_m,to_m) values (6,1,2010,90,100);
insert into table_b (id,road_id,year,from_m,to_m) values (7,1,2010,5,85);
insert into table_b (id,road_id,year,from_m,to_m) values (8,1,2015,40,100);
insert into table_b (id,road_id,year,from_m,to_m) values (9,1,2015,0,40);
insert into table_b (id,road_id,year,from_m,to_m) values (10,2,2020,0,41);
insert into table_b (id,road_id,year,from_m,to_m) values (11,3,2025,155,200);
insert into table_b (id,road_id,year,from_m,to_m) values (12,3,2025,199,300);
insert into table_b (id,road_id,year,from_m,to_m) values (13,4,2024,5,355);
commit;

select * from table_b;

        ID    ROAD_ID       YEAR     FROM_M       TO_M
---------- ---------- ---------- ---------- ----------
         1          1       1995          0        100
         2          1       2001          0         50
         3          1       2005         20         80
         4          1       2005          0        100
         5          1       2010          0         10
         6          1       2010         90        100
         7          1       2010          5         85
         8          1       2015         40        100
         9          1       2015          0         40
        10          2       2020          0         41
        11          3       2025        155        200
        12          3       2025        199        300
        13          4       2024          5        355

【问题讨论】:

  • 根据您的要求,您的红色和绿色不合适请检查。
  • @nikhilsugandh 你能告诉我哪些是错的吗?
  • 你的问题我不清楚,虽然我试图给你解决方案。
  • 请参阅下面的答案,但您已经接受了一个。我已经按照您的要求编辑了我的帖子并带有输出。

标签: oracle select range oracle12c between


【解决方案1】:

一个不存在的子选择在这里可以提供帮助

SELECT *
FROM table_b b
WHERE
    NOT EXISTS (SELECT *
                FROM table_a a
                WHERE
                    a.road_id = b.road_id AND
                    a.year = b.year AND
                    a.to_m > b.from_m AND
                    a.from_m < b.to_m)

让我们看看重叠范围(f=from, t=to)

a   -------------------f=======================t-----------------

b1a -----f=============t-----------------------------------------
b1b --f=============t--------------------------------------------

b2a -------------------------------------------f======t----------
b2b -----------------------------------------------f======t------

b3  ---------------f=========t-----------------------------------
b4  ------------------------f===========t------------------------
b5  ---------------------------------------f===========t---------

范围 b3、b4 和 b5 重叠。对于所有这些,以下都是正确的

a.to > b.from && a.from < b.to

对于不重叠的 b1a、b1b 和 b2a、b2b,此条件为假。对于 b1a a.from == b.to,对于 b1b a.from &gt; b.to,因此条件 a.from &lt; b.to 是 false。

对于 b2a a.to == b.from,对于 b2b a.to &lt; b.from,因此条件 a.to &gt; b.from 是 false。

诀窍是将一个范围的from 与另一个范围的to 进行比较,反之亦然。

见:http://sqlfiddle.com/#!4/85883/3/0

【讨论】:

【解决方案2】:

这会起作用:

SELECT * FROM table_b b
WHERE
    EXISTS (SELECT *
                FROM table_a a
                WHERE
                 a.year=b.year and a.from_m<>b.from_m and  a.to_m <>b.to_m );

【讨论】:

  • OP 想要不重叠的部分,因为您的答案发现记录具有不同的部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 2020-04-24
  • 2018-03-03
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多