Oracle-将每小时数据从行转换为列

时间:2018-12-08 22:18:37

标签: sql oracle datetime pivot transpose

我有一个Oracle表,其中填充了与日期时间相关的数据行。

EX:

Value     Datetime
-----     ----------------
123       12/08/2018 00:00
456       12/08/2018 01:00
789       12/08/2018 02:00
...       ...
312       12/08/2018 23:00
321       12/09/2018 00:00
...       ...

我需要获取此数据并将其按天分组,但是以某种方式将每小时数据在24小时内每小时转换为一列。

EX:

Date          Value(00:00)     Value(01:00)     Value(02:00)     ...     Value(23:00) 
----          ------------     ------------     ------------     ---     ------------
12/08/2018    123              456              789              ...     312
12/09/2018    321              654              987              ...     423
...           ...              ...              ...              ...     ...

查询以这种格式从表中获取数据的最有效方法是什么?如果这个问题已经回答,我深表歉意。我在网上搜索了很多内容,但老实说,即使知道正确的关键字来搜索此答案,我还是有些矛盾。预先谢谢你。

2 个答案:

答案 0 :(得分:0)

我已尽力简化答案,以解决堆栈溢出问题。我能够使用类似于下面的查询来格式化信息。

SELECT date,
       SUM(CASE WHEN EXTRACT(HOUR FROM datetime) >= 0 AND EXTRACT(HOUR FROM datetime) < 1  THEN value ELSE 0 END) as "value(00:00)",
       SUM(CASE WHEN EXTRACT(HOUR FROM datetime) >= 1 AND EXTRACT(HOUR FROM datetime) < 2  THEN value ELSE 0 END) as "value(01:00)",
       SUM(CASE WHEN EXTRACT(HOUR FROM datetime) >= 2 AND EXTRACT(HOUR FROM datetime) < 3  THEN value ELSE 0 END) as "value(02:00)",
                ...
       FROM (
            SELECT TO_CHAR(datetime,'YYYY-MM-DD') AS date,
                   value,
                   datetime
            FROM table
       )
GROUP BY date

答案 1 :(得分:0)

获取行并将其转换为列的过程称为透视。从11g(?)开始,Oracle使用PIVOT关键字来本地执行此操作。请注意,Oracle中没有“时间”数据类型,因此在进行数据透视之前将它们转换为两位数字符。数据透视表中必须有一个汇总函数,因此请确保您没有重复的日期相同的行。

select * from (
  select "Value", to_char( "Datetime", 'HH24' ) as dt from table1
)
pivot ( max( "Value" ) for ( dt ) in ( '00' AS "hour0", 
    '01' as "hour1", '02' as "hour2" ));

编辑:

要按天汇总,忽略时间部分,请在嵌入式视图中添加一个TRUNCed列。

select * from (
  select "Value", trunc("Datetime") as the_day, 
         to_char( "Datetime", 'HH24' ) as dt from table1
)
pivot ( max( "Value" ) for ( dt ) in ( '00', '01', '02' ));

SQL Fiddle 2