使用滞后计算行之间的差异

时间:2019-07-29 13:34:37

标签: sql oracle oracle11g

我正试图确定零件从完成到销售的时间(试图弄清楚库存中的库存时间是否太长)

我的数据如下:

| SaleID | ProductFinished | ProductSold |
|:------:|:---------------:|:-----------:|
|   100  |     5/1/2019    |   6/1/2019  |
|   200  |     7/1/2019    |   7/3/2019  |
|   300  |    6/23/2019    |  6/30/2019  |
|   400  |    6/20/2019    |  6/21/2019  |
|   500  |    4/21/2019    |  5/21/2019  |
|   600  |    5/11/2019    |  6/20/2019  |

And here is an SQL Fiddle with that table

我需要计算当前行的ProductSold值和上一行的ProductFinished值之间的差,然后将该差分配给当前行的SittingTimer列。我的目标数据集如下:

| SaleID | ProductFinished | ProductSold | SittingTimer |
|:------:|:---------------:|:-----------:|:------------:|
|   100  |     5/1/2019    |   6/1/2019  |     NULL     |
|   200  |     7/1/2019    |   7/3/2019  |      63      |
|   300  |    6/23/2019    |  6/30/2019  |      -1      |
|   400  |    6/20/2019    |  6/21/2019  |      -2      |
|   500  |    4/21/2019    |  5/21/2019  |      -30     |
|   600  |    5/11/2019    |  6/20/2019  |      60      |

我已经阅读了Oracle's LAG function,并且看到了一些使用LAG的帖子like this,但是我似乎无法使其正常工作。

我尝试了以下操作:

SELECT
  tblSales.*,
  TO_NUMBER(LAG(ProductFinished - ProductSold, 1, 0) OVER (ORDER BY SaleID)) AS SittingTimer

 FROM
   tblSales

但是得到这个结果是

SALEID  PRODUCTFINISHED     PRODUCTSOLD     SITTINGTIMER
100     2019-04-30T00:00:00Z    2019-05-31T00:00:00Z    0
200     2019-06-30T00:00:00Z    2019-07-02T00:00:00Z    -31
300     2019-06-22T00:00:00Z    2019-06-29T00:00:00Z    -2
400     2019-06-19T00:00:00Z    2019-06-20T00:00:00Z    -7
500     2019-04-20T00:00:00Z    2019-05-20T00:00:00Z    -1
600     2019-05-10T00:00:00Z    2019-06-19T00:00:00Z    -30

我要去哪里错了?我应该避免使用LAG吗?

3 个答案:

答案 0 :(得分:2)

使用以下查询,您需要lead()分析函数

SELECT
  tblSales.*, lead("ProductSold") over(order by "SaleID")-"ProductFinished" as  prf 

 FROM
   tblSales

输出

SaleID  ProductFinished     ProductSold                SITTINGTIMER
100     2019-04-30 20:00:00.0   2019-05-31 20:00:00.0   63 0:0:0.0
200     2019-06-30 20:00:00.0   2019-07-02 20:00:00.0   -1 0:0:0.0
300     2019-06-22 20:00:00.0   2019-06-29 20:00:00.0   -2 0:0:0.0
400     2019-06-19 20:00:00.0   2019-06-20 20:00:00.0   -30 0:0:0.0
500     2019-04-20 20:00:00.0   2019-05-20 20:00:00.0   60 0:0:0.0
600     2019-05-10 20:00:00.0   2019-06-19 20:00:00.0   (null)

答案 1 :(得分:2)

您应该从滞后结果中减去当前行的值;不能在滞后函数中减去:

SELECT
  tblSales.*,
  LAG("ProductFinished", 1) OVER (ORDER BY "SaleID") - "ProductSold" AS SittingTimer

 FROM
   tblSales;

    SaleID ProductFinished         ProductSold             SITTINGTIMER
---------- ----------------------- ----------------------- ------------
       100 30-Apr-2019 08:00:00 PM 31-May-2019 08:00:00 PM             
       200 30-Jun-2019 08:00:00 PM 02-Jul-2019 08:00:00 PM          -63
       300 22-Jun-2019 08:00:00 PM 29-Jun-2019 08:00:00 PM            1
       400 19-Jun-2019 08:00:00 PM 20-Jun-2019 08:00:00 PM            2
       500 20-Apr-2019 08:00:00 PM 20-May-2019 08:00:00 PM           30
       600 10-May-2019 08:00:00 PM 19-Jun-2019 08:00:00 PM          -60

6 rows selected. 

这使您“当前行的ProductSold值与上一行的ProductFinished值之间存在差异”;交换那些值的符号会更改值的减去顺序:

SELECT
  tblSales.*,
  "ProductSold" - LAG("ProductFinished", 1) OVER (ORDER BY "SaleID") AS SittingTimer

 FROM
   tblSales;

    SaleID ProductFinished         ProductSold             SITTINGTIMER
---------- ----------------------- ----------------------- ------------
       100 30-Apr-2019 08:00:00 PM 31-May-2019 08:00:00 PM             
       200 30-Jun-2019 08:00:00 PM 02-Jul-2019 08:00:00 PM           63
       300 22-Jun-2019 08:00:00 PM 29-Jun-2019 08:00:00 PM           -1
       400 19-Jun-2019 08:00:00 PM 20-Jun-2019 08:00:00 PM           -2
       500 20-Apr-2019 08:00:00 PM 20-May-2019 08:00:00 PM          -30
       600 10-May-2019 08:00:00 PM 19-Jun-2019 08:00:00 PM           60

它还假设您的列是日期而不是时间戳-因为如果查询是时间戳,则查询会因ORA-00932错误而出错;但我还是保留了SQL Fiddle中带引号的标识符,因为它们必须出于某种原因而存在。 (您的问题数据和查询与您的小提琴不匹配会令人困惑...)

答案 2 :(得分:0)

如果您使用时间戳,则需要使用时间戳中的提取日期来找到所需的结果,如下所示:

SELECT
    "SaleID",
    "ProductFinished",
    "ProductSold",
    EXTRACT(DAY FROM "ProductSold" - LAG("ProductFinished") OVER(
        ORDER BY
            "SaleID"
    )) AS SITTINGTIMER
FROM
    TBLSALES

输出:

enter image description here

db<>fiddle demo

干杯!