沿线插入日期

Wil*_*son 5 oracle oracle-12c computed-column date-math

road_conditionOracle 12c 中有一张表:

create table road_condition (
    cond_id number(5,0),
    road_id number(5,0),
    cond_date date,
    condition number(5,0)
);

insert into road_condition (cond_id,road_id,cond_date,condition)
values (1,100,to_date('01-NOV-84','DD-MON-RR'),18);
insert into road_condition (cond_id,road_id,cond_date,condition)
values (2,100,to_date('01-JAN-09','DD-MON-RR'),6);
insert into road_condition (cond_id,road_id,cond_date,condition)
values (3,100,to_date('19-JUN-12','DD-MON-RR'),4);
insert into road_condition (cond_id,road_id,cond_date,condition)
values (4,100,to_date('29-APR-15','DD-MON-RR'),4);
insert into road_condition (cond_id,road_id,cond_date,condition)
values (5,200,to_date('29-APR-92','DD-MON-RR'),20);
insert into road_condition (cond_id,road_id,cond_date,condition)
values (6,200,to_date('05-APR-17','DD-MON-RR'),3);
commit;
Run Code Online (Sandbox Code Playgroud)

结果表数据:

COND_ID ROAD_ID   COND_DAT CONDITION
------- -------   -------- ---------
      1     100   84-11-01        18
      2     100   09-01-01         6
      3     100   12-06-19         4
      4     100   15-04-29         4
      5     200   92-04-29        20
      6     200   17-04-05         3
Run Code Online (Sandbox Code Playgroud)

这是一张道路图#100

100号公路图

Condition 表中的分类如下:

  • 20 至 15 人状况良好,不需要任何治疗
  • 14 到 11需要叠加处理
  • 10 到 8需要全深度去除 (FDR) 治疗
  • 7比0需要重建治疗

Condition是从0 到 20, 20 是一条完美的道路。

检查道路时,条件存储为整数(整数),而不是小数。

题:

我不想将图中的线条显示为单一颜色(蓝色),而是想将线条作为彩色类别进行条纹化。

road #100在 Excel 中模拟过:

道路100的Excel图表

主意:

要按所述对数据进行条带化/分类,我想我需要在沿线的每个范围的开始和结束处创建虚拟点(行)

也许最简单的方法是在条件的所有间隔处创建点(行),而不仅仅是在每个范围的开始和结束处。

我使用的绘图软件会在图表中为每个 Y 列/系列创建一条新线(类似于 Excel 的方式)。

因此,我相信我需要将每个类别隔离在单独的列中,以便将其绘制为单独的线(具有单独的颜色)。

此外,每个类别之间需要重叠,以便绘图软件不会显示线条之间的间隙。

如何创建虚拟行(插入日期)?


更新:

我在这里有一个相关的问题:日期为 x 轴:如何乘除日期?

Bal*_*app 5

玩得开心。

with
  num_years as (select extract(year from max(cond_date)) - extract(year from min(cond_date)) +1 as years from road_condition where road_id = 100),
  generated_dates as (select add_months(trunc((select min(cond_date) from road_condition where road_id = 100), 'YYYY'), (rownum - 1) * 12) as cond_date from dual connect by level <= (select years from num_years)),
  generated_data as (select rc.cond_id, rc.road_id,nvl(rc.cond_date, gd.cond_date) as cond_date, rc.condition
    from generated_dates gd left join (select * from road_condition where road_id = 100) rc on (gd.cond_date = trunc(rc.cond_date, 'YYYY'))
  ),
  data1 as (select
      last_value(cond_id ignore nulls) over (order by cond_date) as cond_id,
      cond_id as original_cond_id,
      road_id, cond_date, condition,
      last_value(condition ignore nulls) over (order by cond_date) as s1,
      lead(condition ignore nulls) over (order by cond_date) as s2
    from generated_data
  ),
  data2 as (
    select
      cond_id, road_id, original_cond_id, cond_date, condition, s1, s2,
      count(*) over (partition by cond_id) + 1 as s,
      count(*) over (partition by cond_id order by cond_date rows between unbounded preceding and current row) as s0
   from data1
  ),
  data3 as (
    select original_cond_id as cond_id, road_id, cond_date, 
     round(nvl(condition, (1-s0/s)*(s1-s2)+s2)) as condition
    from data2
  ),
  final_data as (
    select cond_id, road_id, cond_date,
      case when condition between 15 and 20 then condition end as cond_good,
      case when condition between 11 and 14 then condition end as cond_overlay,
      case when condition between 8 and 10 then condition end as cond_fdr,
     case when condition between 0 and 7 then condition end as cond_recon
    from data3
  ),
  data_for_graph as 
  (
    select 
      cond_id, road_id, cond_date, cond_good,
      case when cond_good is not null and lead(cond_overlay) over (order by cond_date) is not null then cond_good else cond_overlay end as cond_overlay,
      case when cond_overlay is not null and lead(cond_fdr) over (order by cond_date) is not null then cond_overlay else cond_fdr end as cond_fdr,
      case when cond_fdr is not null and lead(cond_recon) over (order by cond_date) is not null then cond_fdr else cond_recon end as cond_recon
    from final_data
  )
select * from data_for_graph order by cond_date;
Run Code Online (Sandbox Code Playgroud)

输出:

   COND_ID    ROAD_ID COND_DATE   COND_GOOD COND_OVERLAY   COND_FDR COND_RECON
---------- ---------- ---------- ---------- ------------ ---------- ----------
         1        100 1984-11-01         18                                   
                      1985-01-01         17                                   
                      1986-01-01         17                                   
                      1987-01-01         16                                   
                      1988-01-01         16                                   
                      1989-01-01         15                                   
                      1990-01-01         15           15                      
                      1991-01-01                      14                      
                      1992-01-01                      14                      
                      1993-01-01                      13                      
                      1994-01-01                      13                      
                      1995-01-01                      12                      
                      1996-01-01                      12                      
                      1997-01-01                      12                      
                      1998-01-01                      11                      
                      1999-01-01                      11         11           
                      2000-01-01                                 10           
                      2001-01-01                                 10           
                      2002-01-01                                  9           
                      2003-01-01                                  9           
                      2004-01-01                                  8           
                      2005-01-01                                  8          8
                      2006-01-01                                             7
                      2007-01-01                                             7
                      2008-01-01                                             6
         2        100 2009-01-01                                             6
                      2010-01-01                                             5
                      2011-01-01                                             5
         3        100 2012-06-19                                             4
                      2013-01-01                                             4
                      2014-01-01                                             4
         4        100 2015-04-29                                             4
Run Code Online (Sandbox Code Playgroud)

您可以按照我列出的顺序从最后一行中的 CTE 中进行选择(so select * from num_years、 then select * from generated_dates、 thenselect * from generated_data等等),从而按照步骤进行操作。


Wil*_*son 1

我想我可能已经用这种相对简单的方法破解了它。

它假设道路寿命已知,而不是状况日期。更多信息请参见:日期作为 x 轴:如何乘除日期?

它使用简单的数学来获取线串每段的斜率和 y 轴截距。然后交叉连接到数字表(条件数字)以在每个条件间隔生成点。

create table numbers_condition 
   (    
    numbers number(4,0)
    );
insert into numbers_condition numbers values (20);
insert into numbers_condition numbers values (19);
insert into numbers_condition numbers values (18);
insert into numbers_condition numbers values (17);
insert into numbers_condition numbers values (16);
insert into numbers_condition numbers values (15);
insert into numbers_condition numbers values (14);
insert into numbers_condition numbers values (13);
insert into numbers_condition numbers values (12);
insert into numbers_condition numbers values (11);
insert into numbers_condition numbers values (10);
insert into numbers_condition numbers values (9);
insert into numbers_condition numbers values (8);
insert into numbers_condition numbers values (7);
insert into numbers_condition numbers values (6);
insert into numbers_condition numbers values (5);
insert into numbers_condition numbers values (4);
insert into numbers_condition numbers values (3);
insert into numbers_condition numbers values (2);
insert into numbers_condition numbers values (1);
insert into numbers_condition numbers values (0);
commit;
Run Code Online (Sandbox Code Playgroud)
with a as
    (
    select
        cond_id,
        road_id,
        x1,
        y1,
        x2,
        y2,
        (y2-y1)/(x2-x1) as m_slope,
        y1-((y2-y1)/(x2-x1))*x1 as y_intercept
    from
        (
        select
            cond_id,
            road_id,
            cond_date - to_date('1980-01-01', 'YYYY-MM-DD') as x1,
            condition as y1,
            lead(cond_date - to_date('1980-01-01', 'YYYY-MM-DD')) over (partition by road_id order by cond_date) as x2,
            lead(condition,1,condition)                           over (partition by road_id order by cond_date) as y2
        from
            road_condition
        )
    )
select distinct
    a.road_id,
    case when m_slope <> 0 then ((b.numbers - y_intercept)/m_slope) + to_date('1980-01-01', 'YYYY-MM-DD') else a.x1 + to_date('1980-01-01', 'YYYY-MM-DD') end as cond_date,
    case when b.numbers between 15 and 20 then b.numbers end as cond_good,
    case when b.numbers between 11 and 15 then b.numbers end as cond_overlay,
    case when b.numbers between 8 and 11 then b.numbers end as cond_fdr,
    case when b.numbers between 0 and 8 then b.numbers end as cond_recon
from
    a
cross join
    numbers_condition b
where
    b.numbers between a.y1 and a.y2
    or b.numbers between a.y2 and a.y1
order by
    road_id,
    cond_date
;
Run Code Online (Sandbox Code Playgroud)

注意:我无法弄清楚如何设置子句where以仅从交叉连接中获取我想要的记录(一些垃圾/重复记录输出到结果集)。当存在没有斜率或具有正斜率的线段时,情况会变得有点复杂。所以我采取了简单的方法,只是通过 消除了重复项selecting distinct


   ROAD_ID COND_DAT  COND_GOOD COND_OVERLAY   COND_FDR COND_RECON
---------- -------- ---------- ------------ ---------- ----------
       100 84-11-01         18                                   
       100 86-11-06         17                                   
       100 88-11-11         16                                   
       100 90-11-16         15           15                      
       100 92-11-21                      14                      
       100 94-11-26                      13                      
       100 96-12-01                      12                      
       100 98-12-07                      11         11           
       100 00-12-11                                 10           
       100 02-12-17                                  9           
       100 04-12-21                                  8          8
       100 06-12-27                                             7
       100 09-01-01                                             6
       100 10-09-25                                             5
       100 12-06-19                                             4
       100 15-04-29                                             4

       200 92-04-29         20                                   
       200 93-10-16         19                                   
       200 95-04-05         18                                   
       200 96-09-22         17                                   
       200 98-03-11         16                                   
       200 99-08-29         15           15                      
       200 01-02-15                      14                      
       200 02-08-04                      13                      
       200 04-01-22                      12                      
       200 05-07-11                      11         11           
       200 06-12-29                                 10           
       200 08-06-16                                  9           
       200 09-12-04                                  8          8
       200 11-05-24                                             7
       200 12-11-09                                             6
       200 14-04-29                                             5
       200 15-10-17                                             4
       200 17-04-05                                             3
Run Code Online (Sandbox Code Playgroud)

受到这个问题的其他答案和我之前的问题的启发:Cross join on a numeric table to get line vertices,是否有更好的方法?