2016-05-13 57 views
0

我正尝试从数据库中的两个表重建数据。第一个表格(数据)包含时间值和代码。第二个表格(信号)包含代码和说明。理想情况下,我想最终得到如下所示的结果表格,其中按时间戳分组的列和行名称已更改为描述符文本。重建两个表中的数据并重命名表数据中的行

我已经设法做到这一职位SQL查询使用分组和多个转置,但这并不能很好地扩展。

是否可以在SQL查询中执行所有这些功能?

数据表

TIMESTAMP   CODE  VALUE 
2016-05-11 13:56:47 1000.ME  26.900 
2016-05-11 13:56:47 1313.ME  9.1136 
2016-05-11 13:56:51 1313.ME  9.1233 
2016-05-11 13:56:56 1313.ME  9.1136 
2016-05-11 13:57:00 1000.ME  27 
2016-05-11 13:57:00 1313.ME  9.1331 

信号表

CODE  DESCRIPTOR 
1000.ME Inlet Thermpcouple 
1313.ME Air Flow 

结果表

Timestamp    Inlet Thermpcouple Air Flow 
2016-05-11 13:56:47 26.900    9.1136 
2016-05-11 13:56:51 26.900    9.1233 
2016-05-11 13:56:56 26.900    9.1136 
2016-05-11 13:57:00 27     9.1331 
+0

在你想要的输出中,为什么第二排和第三排有26.900?对于那个时间戳,你对Inlet Thermpcouple没有任何价值,那么你如何选择26.900而不是27或者null? – Aleksej

+0

您不能动态地使用信号表中的行来确定结果集中的列。 (无论如何,除非你想用XML输出)。使用固定值,您可以轻松获取该数据,但不能使用动态值。 –

+0

@AlexPoole - 哈,我很高兴我提到过,否则我不得不编辑我的帖子。:-) – mathguy

回答

1

好做法,感谢您发布您的问题!

这里有一种方法来做你需要的。这个问题有三个部分:首先,您需要连接两个表,以便使用实际的描述符而不是代码。其次,您需要旋转,以便将入口热电偶和气流读数分为两列。第三,如果只有一个时间戳,你只有一个空气流量值,但是入口热电偶没有值,你希望IT值填充最近的读数(值)。

该联接很简单,第三部分是IGNORE NULLS选项的LAG()函数的直接应用。 (注意 - 这个函数允许使用一个开窗子句;默认是rows between unbounded preceding and current row,这正是我们需要的,所以我没有使用这个参数 - 默认是完美的。)

唯一的小故障是 - 除非你使用动态SQL - 您需要必须知道您在SQL语句中使用的每个表中的列的数量和名称。因此,在您的表格中将“入口热电偶”和“气流”描述为无效 - 在声明中它们仍然是硬编码。因此,您可以使用这种方式来编写查询,或者您需要开发动态SQL代码。

下面是代码,包括您的测试数据,然后是查询的输出。

with data_table (ts, code, val) as (
     select to_timestamp('2016-05-11 13:56:47', 'yyyy-mm-dd hh24:mi:ss'), 
                '1000.ME', 26.9  from dual union all 
     select to_timestamp('2016-05-11 13:56:47', 'yyyy-mm-dd hh24:mi:ss'), 
                '1313.ME', 9.1136 from dual union all 
     select to_timestamp('2016-05-11 13:56:51', 'yyyy-mm-dd hh24:mi:ss'), 
                '1313.ME', 9.1233 from dual union all 
     select to_timestamp('2016-05-11 13:56:56', 'yyyy-mm-dd hh24:mi:ss'), 
                '1313.ME', 9.1136 from dual union all 
     select to_timestamp('2016-05-11 13:57:00', 'yyyy-mm-dd hh24:mi:ss'), 
                '1000.ME', 27  from dual union all 
     select to_timestamp('2016-05-11 13:57:00', 'yyyy-mm-dd hh24:mi:ss'), 
                '1313.ME', 9.1331 from dual 
    ), 
    signals_table (code, descriptor) as (
     select '1000.ME', 'Inflow Thermocouple' from dual union all 
     select '1313.ME', 'Air Flow'   from dual 
    ), 
    j as (
     select d.ts, s.descriptor, d.val from data_table d 
            inner join signals_table s on d.code = s.code 
    ), 
    p as (
     select * from j 
      pivot (min(val) for descriptor in ('Inflow Thermocouple' as it, 
               'Air Flow' as af)) 
    ) 
select ts, last_value(it ignore nulls) over (order by ts) as "Inflow Thermocouple", 
      last_value(af ignore nulls) over (order by ts) as "Air Flow" 
from p 
order by ts; 

注 - 下面的输出显示了实际的时间戳数据类型;我不确定您的“timestamp”列是否实际上是DATE数据类型或真正的时间戳,查询应该以任何方式工作。另外,在数据库中使用Oracle关键字(如“timestamp”或“date”)作为表名或列名通常是一个非常糟糕的主意。我改变了ts。

TS           Inflow Thermocouple Air Flow 
--------------------------------------------- ------------------- ---------- 
11-MAY-16 01.56.47.000000000         26.9  9.1136 
11-MAY-16 01.56.51.000000000         26.9  9.1233 
11-MAY-16 01.56.56.000000000         26.9  9.1136 
11-MAY-16 01.57.00.000000000         27  9.1331 
+0

是的,我有一个类似的解决方案,我决定不发布;但信号表是无关紧要的,因为无论如何,您可以直接从数据表中进行数据透视,从而对数据进行硬编码。那么,我想我假设固定代码,你只是假设固定描述符,这是更灵活一点。在信号表中添加一个新行需要修改查询来匹配。 –

+0

右键 - 例如,我假设可能有多个代码分配给气流读数。如果有更多的描述符,只需要修改查询;如果有更多行将不同(新)代码分配给流入热电偶或气流,则查询不需要改变。 – mathguy

+0

不够公平,使用描述符使得查询的重要部分更加清晰。我仍然认为OP需要一个动态的答案,但这可能与他们在普通SQL中获得的答案一样接近。 –