我有一个应用程序可以跟踪文件被“尝试”从一个服务器移动到另一个服务器,以及何时“成功”或“失败”。“尝试”应始终与“成功”或“失败”。但是,我遇到了孤儿的尝试......这意味着没有任何成功或失败的尝试。从another question我问过,我能够隔离被认为是孤儿的 e_ids 。但是,我不想在最终输出中返回“非孤立”传输。请考虑以下示例输出:
例如,在上面的输出中,e_id 000125 在5/23/2016 11:37:09 PM时完成了传输(尝试 - >成功)。我不想看这个。同样,e_id 000672 在5/25/2016 1:28:36 PM时完成了传输(尝试 - >失败)。我也不想看到这个。我只想要查看孤立的传输,结果集如下所示:
值得注意的是,所有已完成的传输都在一秒内发生(因此,为什么在第一个样本输出中日期显示为相同,实际上它们相差几毫秒)。
最后,我的查询到目前为止如下
--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 :(得分:2)
这是一个不需要任何连接的解决方案;相反,它使用LEAD
分析函数。
Oracle安装程序:
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
答案 1 :(得分: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;