SQL Oracle - 时间轴

Posted

技术标签:

【中文标题】SQL Oracle - 时间轴【英文标题】:SQL Oracle - Pivot with timing 【发布时间】:2014-10-25 23:02:33 【问题描述】:

我有一个 MCU_RAW 表,其中包含一系列不断变化的重复变量。有 23 个不同的变量。

SELECT DISTINCT(N_CODE) "Code" 
FROM MCU_RAW 
WHERE N_LOGTYPE = 2 
AND F_VALUE is not NULL 
ORDER BY N_CODE
--All Rows Fetched: 23 in 17,775 seconds
--[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]

实际数据的缩小预览

SELECT to_char(D_ENTRY, 'YYYY-MM-DD HH24:mi:SS') "DateTime"
       , N_MS "MS"
       , N_CODE "Code"
       , F_VALUE 
FROM mcu_raw
WHERE N_LOGTYPE = 2
AND F_VALUE is not null
AND d_entry < to_Date('2014-10-01 19:04:52', 'YYYY-MM-DD HH24:MI:SS');

看起来像

DateTime                MS      Code    F_VALUE
2014-09-05 09:37:52     153     1       1
2014-09-05 09:37:52     215     2       0
2014-09-05 09:37:52     246     3       3
2014-09-05 09:37:52     278     1       1
2014-09-05 09:37:52     324     2       0
2014-09-05 09:37:52     340     4       292439
2014-09-05 09:37:52     402     1       1
2014-09-05 09:37:52     480     2       0
2014-09-05 09:37:52     512     5       17,26
2014-09-05 09:37:52     605     1       1
2014-09-05 09:37:52     652     2       0
2014-09-05 09:37:52     683     6       24,96
2014-09-05 09:37:52     714     1       1
2014-09-05 09:37:52     777     2       0
2014-09-05 09:37:52     824     7       110
2014-09-05 09:37:53     104     1       2
2014-09-05 09:37:53     136     2       3
2014-09-05 09:37:53     215     3       4

我想做的是将数据从 MCU_RAW 转移到我创建的另一个表 MCU 中。这样做是为了让一行包含序列中第一个代码的时间数据,然后每个代码的列包含最新的值。

SELECT to_char(D_ENTRY, 'YYYY-MM-DD HH24:mi:SS') "DateTime"
       , N_MS "MS"
       , C0001
       , C0002
       , C0003
       , C0004
       , C0006
       , C0007 
   FROM MCU

缩小预览所需的输出是:

DateTime                MS  C0001   C0002   C0003   C0004   C0005   C0006   C0007
2014-09-05 09:37:52     153     1       0       3   (null)  (null)  (null)  (null)
2014-09-05 09:37:52     278     1       0       3   292439  (null)  (null)  (null)
2014-09-05 09:37:52     402     1       0       3   292439  17,26   (null)  (null)
2014-09-05 09:37:52     605     1       0       3   292439  17,26   24,96   (null)
2014-09-05 09:37:52     714     1       0       3   292439  17,26   24,96   110
2014-09-05 09:37:53     104     2       3       4   292439  17,26   24,96   110

到目前为止,我所做的是插入代码 1 以获得每一行的正确时间。

INSERT INTO mcu (D_ENTRY, N_MS, C0001) 
SELECT D_ENTRY, N_MS, F_VALUE
FROM MCU_raw
WHERE  N_CODE = 1 
AND N_LOGTYPE = 2 
AND F_VALUE is not null 
AND d_entry < to_Date('2014-10-01 19:04:52', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY D_ENTRY, N_MS;

从这里开始,我一直把头撞在墙上,试图弄清楚如何将每一行更新为每一列的最新值。

编辑: 我选择在重复序列中第一次出现 N_CODE = 1 时使用 N_MS。

F_VALUE WHERE N_CODE = 1 is C0001
F_VALUE WHERE N_CODE = 2 is C0002
F_VALUE WHERE N_CODE = 3 is C0003

等等……

【问题讨论】:

你需要在这里解释游戏规则。您如何决定采用哪些 N_MS 值?您如何决定将 F_VALUE 分配给 C0001 还是 C0007? 【参考方案1】:
with mcu_raw as (
  select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS') datetime, 153 ms, 1 code, 1 f_value from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     215,     2,       0 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     246,     3,       3 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     278,     1,       1 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     324,     2,       0 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     340,     4,       292439  from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     402,     1,       1 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     480,     2,       0 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     512,     5,       17.26  from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     605,     1,       1 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     652,     2,       0 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     683,     6,       24.96 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     714,     1,       1 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     777,     2,       0 from dual
  union all select to_date('2014-09-05 09:37:52', 'YYYY-MM-DD HH24:MI:SS'),     824,     7,       110 from dual
  union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),     104,     1,       2 from dual
  union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),     136,     2,       3 from dual
  union all select to_date('2014-09-05 09:37:53', 'YYYY-MM-DD HH24:MI:SS'),     215,     3,       4 from dual
),
mcu_raw_tree as (
  select datetime, ms, code, f_value, 
         case when code_prev > code then null else ms_prev end ms_parent
  from (select datetime, ms, code, f_value, 
               lag(code) over(order by datetime, ms) code_prev,
               lag(ms) over(order by datetime, ms) ms_prev
          from mcu_raw)
),
mcu_raw_path as (
  select sys_connect_by_path(code || '_' || f_value, '#') path, 
         connect_by_root datetime datetime,
         connect_by_root ms ms,
         connect_by_isleaf lf, connect_by_root code root
  from mcu_raw_tree
  start with ms_parent is null
  connect by prior ms = ms_parent
),
mcu_raw_parse as (
  select datetime, ms, path, 
         substr(regexp_substr(path, '1_[^#]+', 1, 1), 3) c0001,
         substr(regexp_substr(path, '2_[^#]+', 1, 1), 3) c0002,
         substr(regexp_substr(path, '3_[^#]+', 1, 1), 3) c0003,
         substr(regexp_substr(path, '4_[^#]+', 1, 1), 3) c0004,
         substr(regexp_substr(path, '5_[^#]+', 1, 1), 3) c0005,
         substr(regexp_substr(path, '6_[^#]+', 1, 1), 3) c0006,
         substr(regexp_substr(path, '7_[^#]+', 1, 1), 3) c0007
   from mcu_raw_path where lf = 1 and root = 1
  order by datetime, ms
)
select to_char(datetime, 'YYYY-MM-DD HH24:MI:SS'), ms
     , case when c0001 is null then lag(c0001 ignore nulls) over (order by datetime, ms) else c0001 end c0001
     , case when c0002 is null then lag(c0002 ignore nulls) over (order by datetime, ms) else c0002 end c0002
     , case when c0003 is null then lag(c0003 ignore nulls) over (order by datetime, ms) else c0003 end c0003
     , case when c0004 is null then lag(c0004 ignore nulls) over (order by datetime, ms) else c0004 end c0004
     , case when c0005 is null then lag(c0005 ignore nulls) over (order by datetime, ms) else c0005 end c0005
     , case when c0006 is null then lag(c0006 ignore nulls) over (order by datetime, ms) else c0006 end c0006
     , case when c0007 is null then lag(c0007 ignore nulls) over (order by datetime, ms) else c0007 end c0007
from mcu_raw_parse;
    制作一棵树(为非 1 的代码查找父代) 调用分层查询构建路径 适当解析路径 处理空值 使用插入到选择...

附:您的问题不是 100% 清楚,我主要通过查看“所需输出”来构建此查询

【讨论】:

以上是关于SQL Oracle - 时间轴的主要内容,如果未能解决你的问题,请参考以下文章

SQL中枢轴的变化

尝试显示从 Oracle 数据库中选择的数据时出现 JPGraph 轴错误

将秒格式化为 SQL 报表生成器 Y 轴标签的天、小时、分钟、秒

安卓笔记时间轴在哪

JAVA 时间轴

时光轴 时间轴 效果