查询以生成每天一行的数据集



我有一个非常简单的表:

CREATE TABLE T_ACTIVITY_LOG
(
  ACTIVITY_DATE           TIMESTAMP,
  APPLIANCE_ID            NUMBER(9) DEFAULT 0 NOT NULL,
  APPLIANCE_STATUS        NUMBER(1) DEFAULT 0 NOT NULL
)

记录各种工业设备的状态变化(-1和0)。每次状态被修改时,都会在表中插入一条记录:

APPLIANCE_ID    ACTIVITY_DATE      APPLIANCE_STATUS
----------  ------------------- -----------
         1  01-jan-15 00:00:00  0
         1  11-jan-15 00:00:00  1
         1  21-jan-15 00:00:00  0
         1  30-jan-15 00:00:00  1

现在我正在处理一个报告,我需要生成一个数据集,其中包含一个月中的每一天的一行和相应的设备状态:

APPLIANCE_ID    ACTIVITY_DATE   APPLIANCE_STATUS
----------  ------------------- -----------
         1  01-jan-15 00:00:00  0
         1  02-jan-15 00:00:00  0
         1  03-jan-15 00:00:00  0
         1  04-jan-15 00:00:00  0
         1  05-jan-15 00:00:00  0
         1  06-jan-15 00:00:00  0
         1  07-jan-15 00:00:00  0
         1  08-jan-15 00:00:00  0
         1  09-jan-15 00:00:00  0
         1  10-jan-15 00:00:00  0
         1  11-jan-15 00:00:00  1
         1  12-jan-15 00:00:00  1
         1  13-jan-15 00:00:00  1
         1  14-jan-15 00:00:00  1
         1  15-jan-15 00:00:00  1
         1  16-jan-15 00:00:00  1
         1  17-jan-15 00:00:00  1
         1  18-jan-15 00:00:00  1
         1  19-jan-15 00:00:00  1
         1  20-jan-15 00:00:00  1
         1  21-jan-15 00:00:00  0
         1  22-jan-15 00:00:00  0
         1  23-jan-15 00:00:00  0
         1  24-jan-15 00:00:00  0
         1  25-jan-15 00:00:00  0
         1  26-jan-15 00:00:00  0
         1  27-jan-15 00:00:00  0
         1  28-jan-15 00:00:00  0
         1  29-jan-15 00:00:00  0
         1  30-jan-15 00:00:00  1
         1  31-jan-15 00:00:00  1

是否有可能通过SQL做到这一点,或者我应该在软件中使用临时表来构建数据集?

谢谢!

Oracle支持分区外连接语法,该语法允许在没有行可用的地方填充稀疏数据,并且在本教程中还提供了一种用最近值填充空白的方法。

要达到你的目标需要三个技巧:

  • 生成日期列表
  • 分区外连接
  • LAST_VALUE()分析函数填充"缺失"值

:

with t_activity_log as (select 1 appliance_id, to_date('01/01/2015', 'dd/mm/yyyy') activity_date, 0 appliance_status from dual union all
                        select 1 appliance_id, to_date('11/01/2015', 'dd/mm/yyyy') activity_date, 1 appliance_status from dual union all
                        select 1 appliance_id, to_date('21/01/2015', 'dd/mm/yyyy') activity_date, 0 appliance_status from dual union all
                        select 1 appliance_id, to_date('30/01/2015', 'dd/mm/yyyy') activity_date, 1 appliance_status from dual union all
                        select 2 appliance_id, to_date('02/01/2015', 'dd/mm/yyyy') activity_date, 0 appliance_status from dual union all
                        select 2 appliance_id, to_date('10/01/2015', 'dd/mm/yyyy') activity_date, 1 appliance_status from dual union all
                        select 2 appliance_id, to_date('15/01/2015', 'dd/mm/yyyy') activity_date, 0 appliance_status from dual union all
                        select 2 appliance_id, to_date('26/01/2015', 'dd/mm/yyyy') activity_date, 1 appliance_status from dual),
              dates as (select to_date('01/01/2015', 'dd/mm/yyyy') -1 + level dt
                        from   dual
                        connect by level <= 31) -- query to generate the list of dates; amend as appropriate to get the list of dates you're after
select tal.appliance_id,
       dts.dt,
       last_value(tal.appliance_status ignore nulls) over (partition by tal.appliance_id order by dts.dt) appliance_status
from   dates dts
       left outer join t_activity_log tal partition by (tal.appliance_id) on (dts.dt = tal.activity_date)
order by tal.appliance_id,
         dts.dt;
APPLIANCE_ID DT         APPLIANCE_STATUS
------------ ---------- ----------------
           1 01/01/2015                0
           1 02/01/2015                0
           1 03/01/2015                0
           1 04/01/2015                0
           1 05/01/2015                0
           1 06/01/2015                0
           1 07/01/2015                0
           1 08/01/2015                0
           1 09/01/2015                0
           1 10/01/2015                0
           1 11/01/2015                1
           1 12/01/2015                1
           1 13/01/2015                1
           1 14/01/2015                1
           1 15/01/2015                1
           1 16/01/2015                1
           1 17/01/2015                1
           1 18/01/2015                1
           1 19/01/2015                1
           1 20/01/2015                1
           1 21/01/2015                0
           1 22/01/2015                0
           1 23/01/2015                0
           1 24/01/2015                0
           1 25/01/2015                0
           1 26/01/2015                0
           1 27/01/2015                0
           1 28/01/2015                0
           1 29/01/2015                0
           1 30/01/2015                1
           1 31/01/2015                1
           2 01/01/2015                 
           2 02/01/2015                0
           2 03/01/2015                0
           2 04/01/2015                0
           2 05/01/2015                0
           2 06/01/2015                0
           2 07/01/2015                0
           2 08/01/2015                0
           2 09/01/2015                0
           2 10/01/2015                1
           2 11/01/2015                1
           2 12/01/2015                1
           2 13/01/2015                1
           2 14/01/2015                1
           2 15/01/2015                0
           2 16/01/2015                0
           2 17/01/2015                0
           2 18/01/2015                0
           2 19/01/2015                0
           2 20/01/2015                0
           2 21/01/2015                0
           2 22/01/2015                0
           2 23/01/2015                0
           2 24/01/2015                0
           2 25/01/2015                0
           2 26/01/2015                1
           2 27/01/2015                1
           2 28/01/2015                1
           2 29/01/2015                1
           2 30/01/2015                1
           2 31/01/2015                1

NB。如果第一个appliance_date在日期周期的开始之后(参见2月1日的appliance_id = 2),您没有说明应该发生什么,所以我将其默认为null。如果您不希望显示这些行,则必须在上述SQL周围抛出一个外部查询,以便在appliance_status不为null时进行过滤。

如果你想让它不同,你还必须修改生成日期的查询。在指定的开始日期和结束日期之间,或基于表数据等)。关于如何生成日期列表,有很多示例。

最新更新