2015-09-07 248 views
1

1行中的數據集我有一個非常簡單的表:查詢生成每

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)各種工業設備。 A記錄每個狀態被修改時在表中插入:

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來做到這一點,或者我應該在軟件中使用臨時表來自己創建數據集?

謝謝!

+1

提取日期部分從時間戳,通過做組。 – jarlh

+1

參見[**行發生器方法**](http://lalitkumarb.com/2015/04/15/generate-date-month-name-week-number-day-number-between-two-dates-in -Oracle-SQL /)。 –

回答

4

Oracle支持分區外部連接語法,該語法允許在行不可用的情況下填充稀疏數據,並且在this tutorial中還有一種用最新值填充空白的方法。

1

有以達到你的目標所需的三種技術:

  • 生成日期
  • 分區外部聯接
  • 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是日期期開始後會發生什麼情況(見APPLIANCE_ID = 2的2月1日),所以我離開它默認爲空。如果您不希望顯示這些行,則必須針對上述SQL進行外部查詢,以便在appliance_status上進行篩選並非爲空。

您還可以修改,如果你希望它是不同的(例如,指定的開始和結束日期之間,或者基於表數據等),其產生的日期爲適當的查詢。有很多關於如何生成日期列表的例子。