以下嵌套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);
答案 0 :(得分:0)
使用最简单的解决方案:您的查询不需要任何CTE。一般来说,在
时使用CTE(有一个相关的命名聚合结果集,但可以使用连接的子查询来完成)
对于简单的条件,请不要打扰。以下几乎应该在每个版本的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
)