【问题标题】:Rebuilding data from two tables and renaming rows from table data从两个表重建数据并从表数据重命名行
【发布时间】:2016-05-13 13:26:45
【问题描述】:

我正在尝试从数据库中的两个表中重建数据。第一个表(数据)包含时间值和代码。第二个表(信号)包含代码和描述。理想情况下,我希望得到下面显示的结果表,其中列按时间戳分组,行名称更改为描述符文本。

我已经设法使用分组和多个转置来完成这个 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

【问题讨论】:

  • 在您想要的输出中,为什么第 2 行和第 3 行有 26.900?对于那个时间戳,您没有 Inlet Thermpcouple 的值,那么您如何选择 26.900 而不是 27 或 null?
  • 你不能动态地这样做,使用信号表中的行来确定结果集中的列,在普通的 SQL 中。 (除非您想要 XML 格式的输出,否则)。使用固定值,您可以轻松获取该数据,但使用动态值则不行。
  • @AlexPoole - 哈,我很高兴我提到了这一点,否则我将不得不编辑我的帖子。 :-)

标签: sql oracle pivot transpose


【解决方案1】:

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

这是满足您需要的一种方法。问题分为三个部分:首先,您需要连接两个表,以便获得实际的描述符而不是代码。其次,您需要旋转,以便将入口热电偶和气流读数分成两列。第三,如果对于一个时间戳,您只有 Air Flow 的值而没有 Inlet Thermocouple 的值,您希望 IT 值填充最新的读数(值)。

连接是微不足道的,第三部分是LAG() 函数与IGNORE NULLS 选项的直接应用。 (注意——这个函数允许一个窗口子句;默认是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;

注意 - 下面的输出显示了实际的时间戳数据类型;我不确定您的“时间戳”列实际上是 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

【讨论】:

  • 是的,我有一个类似的解决方案,我决定不发布;但是信号表无关紧要,因为无论如何您都在对值进行硬编码,因此您可以直接从数据表中进行数据透视。好吧,我想我假设的是固定代码,你只是假设固定的描述符,这更灵活一些。向信号表添加新行需要修改查询以使其仍然匹配。
  • 正确 - 例如,我假设可能有多个代码分配给气流读数。仅当有更多描述符时才需要修改查询;如果有更多行为流入热电偶或气流分配不同的(新)代码,则无需更改查询。
  • 很公平,使用描述符可以使查询的重要部分更加清晰。我仍然认为 OP 想要一个动态的答案,但这可能与他们在普通 SQL 中得到的一样接近。
  • 太好了,感谢您的快速回复!实际上,尽管数据可以运行数小时并且有 30 多个描述符。听起来我需要一些动态 SQL 代码,或者我坚持使用缓慢的解决方案。再次感谢。
猜你喜欢
  • 2022-08-11
  • 2013-03-24
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多