【问题标题】:Oracle SQL - Delete subset of records based on criteria [duplicate]Oracle SQL - 根据条件删除记录子集[重复]
【发布时间】:2021-05-05 10:50:02
【问题描述】:

我有下表

ITEM    LOCATION    EFFECTIVE_DATE  SELLING_RETAIL
00139259    11001   01-JUL-20           2
00139259    11001   08-OCT-19           1
00139259    11001   04-OCT-19           1
00139259    11001   01-JAN-18           2
00139259    11001   04-DEC-17           1
00139259    11001   02-MAR-17           500

我只需要根据降序保留项目、位置和生效日期的三个记录。

让我留下来:

ITEM    LOCATION    EFFECTIVE_DATE  SELLING_RETAIL
00139259    11001   01-JUL-20           2
00139259    11001   08-OCT-19           1
00139259    11001   04-OCT-19           1

其余的都应该删除。

表中有很多item和location,我需要为item/location的组合保留3条记录

【问题讨论】:

    标签: sql oracle sql-delete


    【解决方案1】:

    您想使用ROW_NUMBER 分析函数查找最后三个之后的行,然后使用ROWID 伪列与DELETE 语句关联:

    DELETE FROM table_name
    WHERE ROWID IN (
      SELECT ROWID
      FROM   (
        SELECT ROW_NUMBER() OVER (
                 PARTITION BY item, location ORDER BY effective_date DESC
               ) AS rn
        FROM   table_name
      )
      WHERE  rn > 3
    )
    

    其中,对于您的示例数据:

    CREATE TABLE TABLE_NAME ( ITEM, LOCATION, EFFECTIVE_DATE, SELLING_RETAIL ) AS
    SELECT '00139259', 11001, DATE '2020-07-01', 2 FROM DUAL UNION ALL
    SELECT '00139259', 11001, DATE '2019-10-08', 1 FROM DUAL UNION ALL
    SELECT '00139259', 11001, DATE '2019-10-04', 1 FROM DUAL UNION ALL
    SELECT '00139259', 11001, DATE '2018-01-01', 2 FROM DUAL UNION ALL
    SELECT '00139259', 11001, DATE '2017-12-04', 1 FROM DUAL UNION ALL
    SELECT '00139259', 11001, DATE '2017-03-02', 500 FROM DUAL;
    

    然后删除后:

    SELECT * FROM table_name;
    

    输出:

    ITEM LOCATION EFFECTIVE_DATE SELLING_RETAIL
    00139259 11001 2020-07-01 00:00:00 2
    00139259 11001 2019-10-08 00:00:00 1
    00139259 11001 2019-10-04 00:00:00 1

    db小提琴here

    【讨论】:

      【解决方案2】:

      你可以使用row_number():

      select t.*
      from (select t.*,
                   row_number() over (partition by item, location order by EFFECTIVE_DATE desc) as seqnum
            from t
           ) t
      where seqnum <= 3;
      

      这将为所有项目/位置对返回 3 行。如果您只考虑一对,您可以使用:

      select t.*
      from t
      where item = ? and location = ?
      order by effective_date desc
      fetch first 3 rows only;
      

      【讨论】:

      • 我如何用相同的逻辑删除?它给了我“数据操作操作在此视图上不合法”的错误
      猜你喜欢
      • 1970-01-01
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2020-07-15
      • 2021-11-11
      • 1970-01-01
      • 2020-10-07
      相关资源
      最近更新 更多