2016-02-10 49 views
1

在Oracle表中,我有許多不同的唯一ID在15分鐘間隔內傳入數據。例如,數據可能看起來像這樣:在Oracle中,計算日期範圍內缺失間隔的數量

ObjectID  Date 
123   1/1/2016 00:00:00 
123   1/1/2016 00:15:00 
123   1/1/2016 00:30:00 
123   1/1/2016 00:45:00 
123   1/1/2016 01:00:00 
456   1/1/2016 00:00:00 
456   1/1/2016 00:15:00 
456   1/1/2016 00:30:00 
456   1/1/2016 00:45:00 
456   1/1/2016 01:00:00 
789   1/1/2016 00:00:00 
789   1/1/2016 00:15:00 
789   1/1/2016 00:30:00 
789   1/1/2016 00:45:00 
789   1/1/2016 01:00:00 

這是一個非常簡單的例子。實際上,對象ID沒有按照統一的順序排序,並且可能會丟失間隔。因此,數據真的看起來更像是這樣的:

ObjectID  Date 
456   1/1/2016 00:15:00 
456   1/1/2016 00:30:00 
123   1/1/2016 00:30:00 
123   1/1/2016 00:45:00 
123   1/1/2016 01:00:00 
456   1/1/2016 00:45:00 
456   1/1/2016 01:00:00 
789   1/1/2016 00:45:00 
789   1/1/2016 01:00:00 
789   1/1/2016 00:00:00 
789   1/1/2016 00:15:00 
789   1/1/2016 00:30:00 

我希望能夠得到在所有的ObjectID失蹤間隔的計數指定日期範圍。在上文中,有三人失蹤間隔:

123   1/1/2016 00:00:00 
123   1/1/2016 00:15:00 
456   1/1/2016 00:00:00 

我正在尋找一個查詢會趕上這些並返回計數3,如果給定的2016年1月1日00:00:00的日期範圍 - 1/1/2016 1:00:00。

+0

你不關心它的ObjectID有丟失的時間間隔,只是缺少總算? – OldProgrammer

+0

這是正確的。然而,通過objectID計數可能會是一個更好的信息:) – user2276280

回答

1

我覺得像這樣的東西可能會起作用。可能是更有效的方法。

select count(*) from your_table 
where your_table.date not in 
(
SELECT dateval 
FROM 
    (WITH dates AS 
    (SELECT to_date('01/01/2016 00:00:00','MM/DD/YYYY HH24:MI:SS') dstart, 
    to_date('01/01/2016 01:00:00','MM/DD/YYYY HH24:MI:SS') dend 
    FROM dual 
) 
SELECT dstart + rownum/96.0 dateval 
FROM dates 
    CONNECT BY rownum <= 
    (SELECT (dend - dstart)*96 FROM dates 
) 
) 
) 

的「通過連接」計數的開始/結束日期之間15個分鐘的間隔的數量,則每一個生成的日期/時間開始在與開始日期/時間爲15個分鐘的增量。

+1

很好的使用「連接」,而不是最正統的方法,但優雅 – jclozano

1

如果你只需要計數,方式可能是計數的預期區間,並與真正找到間隔數的區別:

with test(ObjectID, Date_) as 
(
    select 456, to_date('1/1/2016 00:15:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:15:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual 
), 
input_dates(start_date, end_date) as 
( select to_date('1/1/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss'), 
      to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual) 
-- 
select (count(distinct objectId) * (input_dates.end_date - input_dates.start_date) * 24 * 5) 
     - 
     sum(
      case when date_ between input_dates.start_date and input_dates.end_date 
         then 1 
         else 0 
      end 
     ) as missing 
from test, input_dates 

objectID這是表中的情況下,但確實在輸入期間沒有任何間隔,這將返回5,說它缺少所有間隔。 如果你想在具有在此期間至少一個間隔的ID只檢查丟失的時間間隔,你可以簡單地從SUM刪除BETWEEN條件,並添加爲WHERE條款

0

讓我來拍吧... (阿列克謝我從你的答案中摘下)。

with 
-- 
-- Test case supplied 
-- 
test(ObjectID, Date_) as 
(
    select 456, to_date('1/1/2016 00:15:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 123, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 456, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:45:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:15:00', 'dd/mm/yyyy hh24:mi:ss') from dual union all 
    select 789, to_date('1/1/2016 00:30:00', 'dd/mm/yyyy hh24:mi:ss') from dual 
), 
-- 
-- Intervals generates all possible 15 minutes intervals within the given parameters 
-- 
intervals (Date_) as 
(
    select to_date('1/1/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss') + ((15/1440) * (level - 1)) 
    from dual 
connect by level <= 24 * (to_date('1/1/2016 01:00:00', 'dd/mm/yyyy hh24:mi:ss') - to_date('1/1/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')) * 4 
) 
-- 
-- Simple minus to find the missing intervals 
-- 
select distinct test.ObjectID, to_char(intervals.Date_ ,'YYYY/MM/DD HH24:MI:SS') dt 
    from test, 
     intervals 
minus 
select test.ObjectID, to_char(test.Date_,'YYYY/MM/DD HH24:MI:SS') dt 
    from test 
/

當我執行缺少間隔:

OBJECTID DT 
---------- ------------------- 
     123 2016/01/01 00:00:00 
     123 2016/01/01 00:15:00 
     456 2016/01/01 00:00:00 
相關問題