【问题标题】:Compare column value with previous record in Oracle将列值与 Oracle 中的先前记录进行比较
【发布时间】:2021-11-11 23:18:24
【问题描述】:

我的oracle表数据如下。

Org_ID Product_ID Order_Month Amount
101 201 JAN-2021 2000
101 201 FEB-2021 2000
101 201 MAR-2021 2000
101 201 APR-2021 1500
101 201 MAY-2021 2000
101 202 JUN-2021 2000
101 202 JUL-2021 2000

我们需要比较之前的金额值,并找到金额不匹配的记录以及关于Product_ID的记录。

我的输出应该如下所示。尝试使用滞后但找不到解决方案。有人可以提供有关如何解决此问题的意见吗?

Org_ID Product_ID Order_Month Amount
101 201 JAN-2021 to MAR-2021 2000
101 201 APR-2021 to APR-2021 1500
101 201 MAY-2021 to MAY-2021 1500
101 202 JUN-2021 to JUL-2021 1500

【问题讨论】:

  • MAY-2021JUL-2021 的金额是 1500 而不是 2000 有什么原因吗?
  • 在您的示例数据产品中,202 从未有过 1500 的数量,因此不清楚 gow 计算该值

标签: sql oracle


【解决方案1】:

你可以试试下面的

SELECT
    "Org_ID", 
    "Product_ID", 
    CONCAT(
         CONCAT(Order_Month_Group,' to '),
        TO_CHAR(MAX(actual_date),'MON-YYYY')
    ) as Order_Month, 
    "Amount"
FROM (
    SELECT
        t1.*,
        
        LAG(
             "Order_Month",
             CASE WHEN continued=0 THEN 0 ELSE seq_num-1 END
            ,"Order_Month") OVER (
                PARTITION BY "Org_ID","Product_ID","Amount"
                ORDER BY actual_date
        ) as Order_Month_Group
    FROM (
        SELECT 
            t.*,
            TO_DATE(t."Order_Month",'MON-YYYY') as actual_date,
            ROW_NUMBER() OVER (
                PARTITION BY t."Org_ID",t."Product_ID",t."Amount"
                ORDER BY TO_DATE("Order_Month",'MON-YYYY')
            ) as seq_num,
            CASE 
                WHEN t."Amount" = LAG(t."Amount",1,t."Amount") OVER (
                                      PARTITION BY t."Org_ID",t."Product_ID"
                                      ORDER BY TO_DATE("Order_Month",'MON-YYYY')
                                  ) THEN 1 
                ELSE 0 
            END as continued
        FROM 
            my_oracle_table t
    ) t1
) t2
GROUP BY "Org_ID", "Product_ID", Order_Month_Group, "Amount"
ORDER BY MIN(actual_date)

SELECT
    "Org_ID", 
    "Product_ID", 
    CONCAT(
         CONCAT(TO_CHAR(MIN(actual_date),'MON-YYYY'),' to '),
        TO_CHAR(MAX(actual_date),'MON-YYYY')
    ) as Order_Month, 
    "Amount"
FROM (
    SELECT
        t1.*,
        SUM(continued) OVER ( ORDER BY actual_date) as grp
    FROM (
        SELECT 
            t.*,
            TO_DATE("Order_Month",'MON-YYYY') as actual_date,
            CASE 
                WHEN t."Amount" = LAG(t."Amount",1,t."Amount") OVER (
                                      PARTITION BY t."Org_ID",t."Product_ID"
                                      ORDER BY TO_DATE("Order_Month",'MON-YYYY')
                                  ) THEN 0
                ELSE 1 
            END as continued
        FROM 
            my_oracle_table t
    ) t1
) t2
GROUP BY "Org_ID", "Product_ID", grp, "Amount"
ORDER BY MIN(actual_date)

View Demo on DB Fiddle

让我知道这是否适合你。

【讨论】:

    【解决方案2】:

    这是一种孤岛问题。在这种情况下,最简单的解决方案可能是行号的差异。以下假设order_month 实际上是一个字符串(而不是日期):

    select org_id, product_id, amount,
           min(order_month), max(order_month)
    from (select t.*,
                 row_number() over (partition by org_id, product_id order by to_date(order_month, 'MON-YYYY')) as seqnum,
                 row_number() over (partition by org_id, product_id, amount order by to_date(order_month, 'MON-YYYY')) as seqnum_2
          from t
         ) t
    group by org_id, product_id, amount, (seqnum - seqnm_2);
    

    为什么这行得通有点难以解释。但是,如果您查看子查询的结果,您会发现这两个值之间的差异在相邻月份是如何保持不变的。

    【讨论】:

      猜你喜欢
      • 2012-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多