Oracle表中同一列中的前一个字段之间的差异

时间:2014-03-13 16:47:12

标签: sql oracle function

我有一个名为project_errors的表格,其中包含project_idtotal_errorsdate列。因此,每天运行一个批处理作业,在给定的一天插入一行,其中包含特定项目的错误数。

现在我想知道减少了多少错误,以及在一个项目的特定月份引入了多少错误。我想到了一个在插入后创建触发器的解决方案,它将记录错误是增加还是减少并将其放到另一个表中。但这对以前插入的数据不起作用。有没有其他方法可以做到这一点?我研究了滞后函数,但不知道如何解决我的问题。表结构如下。

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

等等......

3 个答案:

答案 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.