2016-06-06 46 views
0

我有一個應用程序可以跟蹤文件何時「試圖」從一臺服務器移動到另一臺服務器,以及它何時「成功」或「失敗」。「嘗試」應該總是與「成功」或「失敗」配對。但是,我遇到了孤立的企圖...意味着已有嘗試沒有任何成功或失敗的報道。從another question我問,我能夠隔離特別是孤兒的e_ids。但是,我不想在最終輸出中返回「非孤兒」傳輸。考慮下面的示例輸出:Oracle SQL - 隔離孤立數據

enter image description here 在上面的輸出,例如,E_ID 具有完成傳輸(嘗試 - >成功)在時間2016年5月23日下午11點37分09秒。我不想看見這個。再次,e_id 在2016年5月25日1:28:36 PM時已完成傳輸(嘗試 - >失敗)。我也不想看到這個。我希望看到的孤立的傳輸,具有結果集看起來像這樣:

enter image description here

這可能是值得指出的是,對方(在一秒鐘內發生,因此,爲什麼在首先完成傳輸樣本輸出日期顯示爲相同,實際上它們之間的差異爲毫秒)。

最後,我查詢迄今如下

--This query shows all data for all contact_id's known to be an orphan 
SELECT * FROM 
(
    SELECT 
     d.* 
    FROM 
     (
      SELECT e_id, COUNT(*) AS attempts FROM e_table 
      WHERE e_comment LIKE '%attempting%' 
      AND e_date >= '23-MAY-2016' 
      AND e_date <= '26-MAY-2016' 
      GROUP BY e_id 
     ) a 
     FULL OUTER JOIN 
     (
      SELECT e_id, COUNT(*) AS successes FROM e_table 
      WHERE e_comment LIKE '%successful%' 
      AND e_date >= '23-MAY-2016' 
      AND e_date <= '26-MAY-2016' 
      GROUP BY e_id 
     ) s 
      ON s.e_id = a.e_id 
     FULL OUTER JOIN 
     (
      SELECT e_id, COUNT(*) AS failures FROM e_table 
      WHERE e_comment LIKE '%failed%' 
      AND e_date >= '23-MAY-2016' 
      AND e_date <= '26-MAY-2016' 
      GROUP BY e_id 
     ) f 
      ON f.e_id = COALESCE(a.e_id, s.e_id) 
     FULL OUTER JOIN 
     (
      SELECT * FROM e_table 
      WHERE e_date >= '23-MAY-2016' 
      AND e_date <= '26-MAY-2016' 
     ) d 
      ON a.e_id = d.e_id   
    WHERE 
     COALESCE(attempts, 0) <> COALESCE(successes, 0) + COALESCE(failures, 0) 
) 
MINUS 
(
    --This is where I'm stuck. I figure, with a MINUS, I can remove the 
    --cases with completed transmissions, thus showing ONLY the orphans. 
) 

任何幫助是極大的讚賞。

+0

''23 -MAY-2016''不是日期 - 它是一個字符串文字。 Oracle會使用'NLS_DATE_FORMAT'會話參數作爲格式掩碼隱式調用'TO_DATE()'。如果這不是「DD-MON-YYYY」,那麼這將失敗並導致查詢錯誤(並且用戶可以改變他們的會話參數,這將導致查詢突然失敗)。最好使用日期文字'DATE'2016-05-23''或使用'TO_DATE()'並明確指定格式掩碼(因爲您使用的是語言特定的月份名稱,您還應指定NLS語言)。日期文字是兩者中較簡單的。 – MT0

+0

謝謝 - 一旦我們獲得核心功能的工作,我將使用明確的日期。 –

回答

0

以下查詢完成我所需要的。而不是使用原始問題中指定的範圍,我拉「昨天的」數據:

SELECT et.* FROM 
(
    SELECT ce_id, e_id FROM e_table et 
    WHERE e_comment LIKE ("attempt") 
    AND e_date >= TO_DATE(TRUNC(SYSDATE-1)) 
    AND e_date <= TO_DATE(TRUNC(SYSDATE-1) || ' 23:59:59', 'DD-MON-YY HH24:MI:SS') 
    AND NOT EXISTS 
    (
     SELECT ce_id, e_id FROM e_table ett 
     WHERE e_comment LIKE ("success") OR e_comment LIKE ("failure") 
     AND et.e_id = ett.e_id 
     AND ett.ce_id > et.ce_id 
    ) 
) orphans, e_table et 
WHERE orphans.ce_id = et.ce_id 
AND orphans.e_id = et.e_id 
ORDER BY et.ce_id ASC; 
2

這是一個不需要任何連接的解決方案;相反,它使用分析函數LEAD

甲骨文設置

CREATE TABLE e_table (ce_id, e_id, e_comment, e_date) AS 
SELECT '472', '125', 'is attempting to move', TIMESTAMP '2016-05-23 09:49:10' FROM DUAL UNION ALL 
SELECT '678', '125', 'is attempting to move', TIMESTAMP '2016-05-23 11:37:09' FROM DUAL UNION ALL 
SELECT '724', '125', 'has successfully moved', TIMESTAMP '2016-05-23 11:37:09' FROM DUAL UNION ALL 
SELECT '983', '034', 'is attempting to move', TIMESTAMP '2016-05-24 17:04:35' FROM DUAL UNION ALL 
SELECT '643', '672', 'is attempting to move', TIMESTAMP '2016-05-25 13:28:36' FROM DUAL UNION ALL 
SELECT '026', '672', 'failed to move',   TIMESTAMP '2016-05-25 13:28:36' FROM DUAL UNION ALL 
SELECT '087', '672', 'is attempting to move', TIMESTAMP '2016-05-24 18:33:35' FROM DUAL; 

查詢

SELECT ce_id, 
     e_id, 
     e_comment, 
     e_date 
FROM (
    SELECT e.*, 
     LEAD(e_comment) 
      OVER (PARTITION BY e_id 
        ORDER BY e_date, 
          DECODE(e_comment, 'is attempting to move', 1, 2) 
       ) AS next_comment 
    FROM e_table e 
) 
WHERE (next_comment IS NULL OR next_comment = 'is attempting to move') 
AND e_comment = 'is attempting to move'; 

輸出

CE_ID E_ID E_COMMENT    E_DATE      
----- ---- ---------------------- ----------------------------- 
983 034 is attempting to move 2016-05-24 17:04:35.000000000 
472 125 is attempting to move 2016-05-23 09:49:10.000000000 
087 672 is attempting to move 2016-05-24 18:33:35.000000000 
+0

謝謝MT0,但是這不會返回預期的結果數量。同樣,我在問題中包含的樣本輸出就是這樣 - 一個非常小的樣本。共有5,460次嘗試,5,347次成功,50次失敗。因此,預期的行數是63行。這個查詢返回106,所以關閉。我在執行之前修改了它 - 在內部select中添加WHERE子句以考慮日期條件,並將註釋邏輯更改爲LIKE'%attemptpting%',如我原來的問題所示。我也必須在DECODE中做到這一點。 –