使用 Common Table 表达式("WITH AS " 子句)的 DELETE 查询

DELETE query with Common Table Expression ("WITH AS " clause)

我正在尝试从我的 Oracle 数据中删除 41.6% 的旧行table(senstrig 是一种日期格式):

DELETE FROM
    (WITH RS AS (SELECT * FROM OLD_WIFISIGN WHERE SENSID= 1 ORDER BY SENSTRIG ASC))
WHERE ROWNUM <= (SELECT COUNT (*)/ 2.4 FROM RS);

但它 returns 一个错误:

ORA-00928 missing SELECT

我已经尝试了几个版本,但都没有成功。

你能帮我看看我怎样才能让这个 "delete from" 可以运行吗?

WITH放在DELETE之前:

WITH RS AS (SELECT * FROM OLD_WIFISIGN WHERE SENSID= 1 ORDER BY SENSTRIG ASC)
DELETE FROM OLD_WIFISIGN 
WHERE ROWNUM <= (SELECT COUNT (*)/ 2.4 FROM RS);

还是有点奇怪,order by的目的是什么?

测试 table,1000 行,全部为 sensid = 1:

create table old_wifisign (sensid, senstrig) as (
  select 1, trunc(sysdate) - level 
    from dual connect by level <= 1000);

删除:

delete 
  from old_wifisign  
  where rowid in (
      select rowid 
        from (
          select rowid, row_number() over (order by senstrig) / count(1) over () rto 
            from old_wifisign 
            where sensid = 1 )
        where rto <= .416)

结果:删除了最旧的 senstrig 的 416 行。请注意,此处仅将 sensid 1 纳入计算,如您的查询所示。

要删除 41.6% 的旧行,请先检查要删除的边界日期,然后再使用它。

解析函数PERCENT_RANK给你最年轻的senstrig你不想删除

with perc_rank as (
select SENSID, SENSTRIG,
PERCENT_RANK()  OVER (ORDER BY senstrig) AS pr
from old_wifisign)
select max(SENSTRIG) from perc_rank 
where pr < .416

比你简单的接受这个日期并执行 DELETE

delete from old_wifisign
where SENSTRIG < 
(with perc_rank as (
  select SENSID, SENSTRIG,
  PERCENT_RANK()  OVER (ORDER BY senstrig) AS pr
  from old_wifisign) 
select max(SENSTRIG) from perc_rank 
where pr < .416
);

无论如何你应该小心考虑 ties - 关于 table 中一半行具有相同 senstrig[=17 的情况=]