我有一个名为project_errors
的表格,其中包含project_id
,total_errors
和date
列。因此,每天运行一个批处理作业,在给定的一天插入一行,其中包含特定项目的错误数。
现在我想知道减少了多少错误,以及在一个项目的特定月份引入了多少错误。我想到了一个在插入后创建触发器的解决方案,它将记录错误是增加还是减少并将其放到另一个表中。但这对以前插入的数据不起作用。有没有其他方法可以做到这一点?我研究了滞后函数,但不知道如何解决我的问题。表结构如下。
Project_Id Total_Errors Row_Insert_Date
1 56 08-MAR-14
2 14 08-MAR-14
3 89 08-MAR-14
1 54 07-MAR-14
2 7 07-MAR-14
3 80 07-MAR-14
等等......
答案 0 :(得分:3)
如果您可以显示所需的输出,它总是有用的。我的猜测是你要从56中减去54并显示在项目1中添加了2个错误,从14减去7表示在项目2中添加了7个错误,从89减去80表示添加了9个错误项目3.假设是这样的
SELECT project_id,
total_errors,
lag( total_errors ) over( partition by project_id
order by row_insert_date ) prior_num_errors,
total_errors -
lag( total_errors ) over( partition by project_id
order by row_insert_date ) difference
FROM table_name
如果您希望NVL
在第一天为0,则可能需要在LAG
附近投放prior_num_errors
。
答案 1 :(得分:1)
除了Justin的回答,您可能还需要考虑更改表格结构。您可以记录实际错误,然后计算它们,而不是仅记录总计。
假设您有一个表结构,如:
CREATE TABLE PROJECT_ERRORS(
project_id INTEGER
error_id INTEGER
stamp DATETIME
)
每条记录都是一个单独的错误(或单独的错误类型),这样可以提供更多的粒度并允许更复杂的查询。
您仍然可以通过以下方式获得总计:
SELECT project_id, COUNT(error_id), TO_CHAR(stamp, 'DD-MON-YY') AS EACH_DAY
FROM PROJECT_ERRORS
GROUP BY project_id, TO_CHAR(stamp, 'DD-MON-YY')
如果我们将这与JUSTIN的真棒答案结合起来:
SELECT
project_id AS PROJECT_ID,
COUNT(error_id) AS TOTAL_ERRORS,
LAG(COUNT(error_id))
OVER(PARTITION BY project_id
ORDER BY TO_CHAR(stamp, 'DD-MON-YY')) AS prior_num_errors,
COUNT(error_id) - LAG(COUNT(error_id))
OVER(PARTITION BY project_id
ORDER BY TO_CHAR(stamp, 'DD-MON-YY') ) AS diff
FROM project_errors
GROUP BY
project_id,
TO_CHAR(stamp, 'DD-MON-YY')
但是现在你也可以看到特定类型的错误,或者在一天的特定时间看一下。
答案 2 :(得分:0)
贾斯汀的信誉。只想粘贴结果。
WITH TEMP
AS (SELECT 1 AS PROJECT_ID,
56 AS TOTAL_ERRORS,
'08-MAR-14' AS ROW_INSERT_DATE
FROM DUAL
UNION ALL
SELECT 2 AS PROJECT_ID,
14 AS TOTAL_ERRORS,
'08-MAR-14' AS ROW_INSERT_DATE
FROM DUAL
UNION ALL
SELECT 3 AS PROJECT_ID,
89 AS TOTAL_ERRORS,
'08-MAR-14' AS ROW_INSERT_DATE
FROM DUAL
UNION ALL
SELECT 1 AS PROJECT_ID,
54 AS TOTAL_ERRORS,
'07-MAR-14' AS ROW_INSERT_DATE
FROM DUAL
UNION ALL
SELECT 2 AS PROJECT_ID,
7 AS TOTAL_ERRORS,
'07-MAR-14' AS ROW_INSERT_DATE
FROM DUAL
UNION ALL
SELECT 3 AS PROJECT_ID,
80 AS TOTAL_ERRORS,
'07-MAR-14' AS ROW_INSERT_DATE
FROM DUAL)
SELECT PROJECT_ID,
TOTAL_ERRORS,
NVL (
TOTAL_ERRORS
- LAG ( TOTAL_ERRORS )
OVER (PARTITION BY PROJECT_ID ORDER BY ROW_INSERT_DATE),
0 )
CHANGES,
ROW_INSERT_DATE
FROM TEMP;
PROJECT_ID TOTAL_ERRORS CHANGES ROW_INSERT_DATE
---------- ------------ ---------- ---------------
1 54 0 07-MAR-14
1 56 2 08-MAR-14
2 7 0 07-MAR-14
2 14 7 08-MAR-14
3 80 0 07-MAR-14
3 89 9 08-MAR-14
6 rows selected.