DB2 delete和with statement

时间:2014-01-09 01:10:02

标签: sql db2 sql-delete

以下嵌套DB2 SQL查询无效。这嵌套了DELETE和WITH语句

delete from ADDRESS 
where 
    ADDRESS_ID in (with     addr (ADDRESS_ID) as (select a.ADDRESS_ID from ADDRESS a where a.MEMBER_ID between 50000000 and 999999999 and a.STATUS='T' and a.LASTCREATE < (current timestamp - 42 days)), 
                addrorder (ADDRESS_ID) as ( select ad.ADDRESS_ID from ADDR ad LEFT OUTER JOIN ORDERS o on o.ADDRESS_ID = ad.ADDRESS_ID where o.ADDRESS_ID is null), 
                addordi (ADDRESS_ID) as ( select ao.ADDRESS_ID from ADDRORDER ao LEFT OUTER JOIN ORDERITEMS oi on oi.ADDRESS_ID=ao.ADDRESS_ID where oi.ADDRESS_ID is null), 
                addordia (ADDRESS_ID) as ( select aoi.ADDRESS_ID from ADDORDI aoi LEFT OUTER JOIN ORDERITEMS oi ON oi.ALLOCADDRESS_ID=aoi.ADDRESS_ID where oi.ALLOCADDRESS_ID is null)
                select distinct aoia.ADDRESS_ID from ADDORDIA aoia LEFT OUTER JOIN HD_MEMBER_SUBSCR ms ON ms.ADDRESS_ID=aoia.ADDRESS_ID where ms.ADDRESS_ID is null fetch first 800000 rows only for read only with ur);

2 个答案:

答案 0 :(得分:0)

使用最简单的解决方案:您的查询不需要任何CTE。一般来说,在

时使用CTE
  1. 你试图抽象出一些连接/操作集(即通常作为视图创建)
  2. 您计划多次引用结果
  3. (有一个相关的命名聚合结果集,但可以使用连接的子查询来完成)

    对于简单的条件,请不要打扰。以下几乎应该在每个版本的DB2中运行(并且禁止FETCH FIRST,几乎每个RDBMS):

    DELETE FROM Address 
    WHERE member_id >= 50000000 
          AND member_id < 1000000000
          AND status = 'T'
          AND lastCreate < CURRENT_TIMESTAMP - 42 DAYS
          AND NOT EXISTS (SELECT '1'
                          FROM Orders
                          WHERE Orders.address_id = Address.address_id)
          AND NOT EXISTS (SELECT '1'
                          FROM OrderItems
                          WHERE OrderItems.addressId = Address.address_id
                                OR OrderIterms.allocAddress_id = Address.address_id)
          AND NOT EXISTS (SELECT '1'
                          FROM HD_Member_Subscr
                          WHERE HD_Member_Subscr.address_id = Address.address_id)
    FETCH FIRST 800000 ROWS ONLY
    WITH UR
    

    (实际上,我想知道FOR READ ONLY是否是问题的一部分。请注意,如果没有ORDER BY子句,行的顺序将是随机的 - 尽管可能address_id )。

    请注意,我已将BETWEEN替换为独占范围(我个人认为应该弃用BETWEEN,并且出于一致性原因,提倡为偶数整数范围明确定义范围。)

答案 1 :(得分:0)

我同意@ Clockwork-Muse你在这里并不真正需要CTE,我认为DB2不支持具有DELETE语句的CTE(至少在LUW上)。

由于您说NOT EXISTS子句的性能不佳,您可以尝试使用LEFT JOIN s替代,但我不确定它会好得多。以下逻辑假定除了地址字段之外的表中的地址字段是用NOT NULL定义的,如果不是这样的话

如果你真的删除了足够的条目,要求你一次要做八十万个条目,那么你可能有很多数据,无论你如何处理它都会相当慢。

另外,为什么你有WITH UR?你真的想删除未提交的行吗?

DELETE FROM Address 
WHERE member_id >= 50000000 
  AND member_id < 1000000000
  AND status = 'T'
  AND lastCreate < CURRENT_TIMESTAMP - 42 DAYS

  AND address_id IN (
    SELECT address_id FROM (
        SELECT
             A.address_ID
            ,ROW_NUMBER() OVER () AS RN
        FROM Address     A
        LEFT JOIN Orders O
          ON O.address_id = A.address_id
        LEFT JOIN OrderItems OI
          ON OI.addressId = A.address_id
        LEFT JOIN OrderItems OI2
          ON OI2.allocAddress_id = A.address_id
        LEFT JOIN HD_Member_Subscr H
          ON H.address_id= A.address_id
        WHERE O.addressId         IS NULL
          AND OI.addressId        IS NULL
          AND OI2.allocAddress_id IS NULL
          AND H.address_id        IS NULL
    ) T1
    WHERE RN <= 800000
  )