簡體   English   中英

如何比較表中的行並在Oracle中保留行中的最高值

[英]How to compare rows in a table and keep the highest values in the row in Oracle

我正在尋找一個查詢,它將當前行值與前一行值進行比較,如果當前和前一個之間的差異百分比小於 10%,則保留前一個值。 我確信使用 oracle 滯后函數可以實現這一點,但我無法找到確切的解決方案。 我試過下面的查詢,但它沒有保留未來行的先前值。 對此的任何幫助將不勝感激。

我使用下面的查詢來獲取結果,但它沒有解決我的問題。

select /*+ parallel(64) */ a, b, c, datevalue, pricevalue, 
        lag(pricevalue,1,0) over (partition by a, b, c order by a, b, c, datevalue) as prev_pricevalue,
        (pricevalue - lag(pricevalue,1,0) over (partition by a, b, c order by a, b, c, datevalue))/pricevalue as diff,
        case 
            when (pricevalue - lag(pricevalue,1,0) over (partition by a, b, c order by a, b, c, datevalue))/pricevalue
                  < 0.1 then lag(pricevalue,1,0) over (partition by a, b, c order by a, b, c, datevalue)
            else pricevalue
            end new_pricevalue
      from table1
      where datevalue between '18-MAY-2019' and '31-MAY-2019';

我有如下數據。 列名稱為 A、B、C、DATE 和 VALUE

A               B       C       DATE        VALUE
16587EA_1005    RETAIL  7207    18/05/2019  7.04
16587EA_1005    RETAIL  7207    19/05/2019  7.04
16587EA_1005    RETAIL  7207    20/05/2019  7.04
16587EA_1005    RETAIL  7207    21/05/2019  7.04
16587EA_1005    RETAIL  7207    22/05/2019  7.04
16587EA_1005    RETAIL  7207    23/05/2019  7
16587EA_1005    RETAIL  7207    24/05/2019  7
16587EA_1005    RETAIL  7207    25/05/2019  7
16587EA_1005    RETAIL  7207    26/05/2019  7
16587EA_1005    RETAIL  7207    27/05/2019  7
16587EA_1005    RETAIL  7207    28/05/2019  7
16587EA_1005    RETAIL  7207    29/05/2019  8
16587EA_1005    RETAIL  7207    30/05/2019  8
16587EA_1005    RETAIL  7207    31/05/2019  8
16587EA_1005    RETAIL  7207    01/06/2019  8.05
16587EA_1005    RETAIL  7207    02/06/2019  8.05
16587EA_1005    RETAIL  7207    03/06/2019  8.05

而且,我想要如下輸出。

A               B       C       DATE        VALUE
16587EA_1005    RETAIL  7207    18/05/2019  7.04
16587EA_1005    RETAIL  7207    19/05/2019  7.04
16587EA_1005    RETAIL  7207    20/05/2019  7.04
16587EA_1005    RETAIL  7207    21/05/2019  7.04
16587EA_1005    RETAIL  7207    22/05/2019  7.04
16587EA_1005    RETAIL  7207    23/05/2019  7.04
16587EA_1005    RETAIL  7207    24/05/2019  7.04
16587EA_1005    RETAIL  7207    25/05/2019  7.04
16587EA_1005    RETAIL  7207    26/05/2019  7.04
16587EA_1005    RETAIL  7207    27/05/2019  7.04
16587EA_1005    RETAIL  7207    28/05/2019  7.04
16587EA_1005    RETAIL  7207    29/05/2019  8
16587EA_1005    RETAIL  7207    30/05/2019  8
16587EA_1005    RETAIL  7207    31/05/2019  8
16587EA_1005    RETAIL  7207    01/06/2019  8
16587EA_1005    RETAIL  7207    02/06/2019  8
16587EA_1005    RETAIL  7207    03/06/2019  8

最好的問候 MMR

不完全是一種簡潔的方法,但遞歸 CTE 可以做到這一點。

WITH CTE AS
(
  -- adding a rank and rownum
  SELECT t.*
  , DENSE_RANK() OVER (ORDER BY a, b, c) AS rnk
  , ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY datevalue) rn
  FROM table1 t
),
RCTE (rnk, rn, a, b, c, datevalue, pricevalue) AS
(
  -- seeding the recursion
  SELECT rnk, rn, a, b, c, datevalue, pricevalue
  FROM CTE
  WHERE rn = 1

  UNION ALL

  -- loop through the records for each rank
  SELECT c.rnk, c.rn, c.a, c.b, c.c, c.datevalue,
  CASE 
  WHEN ABS(r.pricevalue - c.pricevalue) / c.pricevalue < 0.1
  THEN r.pricevalue
  ELSE c.pricevalue
  END
  FROM RCTE r
  JOIN CTE c
    ON c.rnk = r.rnk
   AND c.rn = r.rn + 1
)
SELECT * 
FROM RCTE
ORDER BY rnk, rn;

返回:

\n RNK | 注冊護士 | 一個 | 乙 |  C | 日期值 | 價格值\n --: |  -: |  :- |  :- |  :- |  :-------- |  ---------:\n   1 |  1 |  | 乙 |  | |  2019 年 5 月 18 日 |  7.04\n   1 |  2 |  | 乙 |  | |  2019 年 5 月 19 日 |  7.04\n   1 |  3 |  | 乙 |  | |  19 年 5 月 20 日 |  7.04\n   1 |  4 |  | 乙 |  | |  2019 年 5 月 21 日 |  7.04\n   1 |  5 |  | 乙 |  | |  19 年 5 月 22 日 |  7.04\n   1 |  6 |  | 乙 |  | |  19 年 5 月 23 日 |  7.04\n   1 |  7 |  | 乙 |  | |  19 年 5 月 24 日 |  7.04\n   1 |  8 |  | 乙 |  | |  19 年 5 月 25 日 |  7.04\n   1 |  9 |  | 乙 |  | |  19 年 5 月 26 日 |  7.04\n   1 |  10 |  | 乙 |  | |  19 年 5 月 27 日 |  7.04\n   1 |  11 |  | 乙 |  | |  19 年 5 月 28 日 |  7.04\n   1 |  12 |  | 乙 |  | |  19 年 5 月 29 日 |  8\n   1 |  13 |  | 乙 |  | |  19 年 5 月 30 日 |  8\n   1 |  14 |  | 乙 |  | |  2019 年 5 月 31 日 |  8\n   1 |  15 |  | 乙 |  | |  01-JUN-19 |  8\n   1 |  16 |  | 乙 |  | |  02-JUN-19 |  8\n

db<>fiddle 的測試在這里

我的嘗試 :) 您可以檢測變化是否大於 10% 並在那里使用新值,在其他情況下留空。 然后使用帶有ignore nulls子句的lag

select a, b, c, dv, pv, 
       nvl(cpv, lag(cpv, 1, cpv) ignore nulls over (partition by a, b, c order by dv)) new_pv
  from (
    select a, b, c, dv, pv, ppv, case when rn = 1 or abs((ppv - pv)/pv) > .01 then pv end cpv
      from (
        select a, b, c, datevalue dv, pricevalue pv, 
               row_number() over (partition by a, b, c order by datevalue) rn,
               lag(pricevalue) over (partition by a, b, c order by datevalue) ppv
          from table1))

數據庫小提琴

它應該比@LukStorms 遞歸解決方案更快,這很好並且也有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM