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 - 时间轴的主要内容,如果未能解决你的问题,请参考以下文章
尝试显示从 Oracle 数据库中选择的数据时出现 JPGraph 轴错误