根据其他行的值删除单个数据库表中的行

时间:2014-12-30 14:25:22

标签: sql postgresql postgresql-9.3

我想在Postgres数据库中使用SQL解决相当复杂的要求。我确信这可以在任何订单管理系统中解决,但我找不到任何类似性质的东西。

我有下表(和值):

CREATE TABLE TABLE1 (
    ID varchar(8), 
    ORIG_ID varchar(8), 
    STATUS varchar(8), 
    VALIDITY varchar(8)
);

INSERT INTO TABLE1
    (ID, ORIG_ID, STATUS, VALIDITY)
VALUES
    ('1', '1', 'REPLACED','DAY'), 
    ('2', '1', 'REPLACED','DAY'),
    ('3', '1', 'FILLED','DAY'),
    ('4', '4', 'REJECTED','DAY'),
    ('5', '5', 'PARTIAL','GTC'),
    ('6', '6', 'EXPIRED','GTD'),
    ('7', '7', 'REPLACED','GTD'),
    ('8', '7', 'PARTIAL','GTD'),
    ('9', '9', 'FILLED', 'GTD'),
    ('10', '10', 'NEW', 'DAY'),
    ('11', '11', 'NEW', 'GTD'),
    ('12', '12', 'DFD', 'GTD'),
    ('13', '13', 'REPLACED', 'GTD'),
    ('14', '13', 'FILLED', 'GTD')
;

N.B -

  • 请忽略字段
  • 上的数据类型
  • 决赛桌可能有数千个要处理的条目
  • 如果需要,可以将上述内容直接粘贴到SQL Fiddle中(PostgreSQL 9.3.1)

我的要求是:

删除状态为:

的所有条目
FILLED, EXPIRED, REJECTED, CANCELLED
PARTIAL/NEW - If the VALIDITY is not GTD/GTC (i.e. only DAY)
REPLACED - Unless there are other entries with the same ORIG_ID in a PARTIAL/NEW STATUS and not GTD/GTC (still working orders)

TBD - To Be Deleted:
TBD ('1', '1', 'REPLACED','DAY'), 
TBD ('2', '1', 'REPLACED','DAY'),
TBD ('3', '1', 'FILLED','DAY'),
TBD ('4', '4', 'REJECTED','DAY'),
    ('5', '5', 'PARTIAL','GTC'),
TBD ('6', '6', 'EXPIRED','GTD'),
    ('7', '7', 'REPLACED','GTD'),
    ('8', '7', 'PARTIAL','GTD'),
TBD ('9', '9', 'FILLED', 'GTD'),
TBD ('10', '10', 'NEW', 'DAY'),
    ('11', '11', 'NEW', 'GTD'),
    ('12', '12', 'DFD', 'GTD'),
TBD ('13', '13', 'REPLACED', 'GTD'),
TBD ('14', '13', 'FILLED', 'GTD')

我试过看了,我能找到的壁橱如下:

Delete with join on the same table and limit clause

但是,在纳入上述要求的同时,我无法让它发挥作用。

由于这将在一天结束时运行,我有一些想法,例如更改有效日期的所有条目,将STATUS设置为EXPIRED。然后只是删除它们然后仍然按GTD / GTC命令发出状态问题。我不确定这是否比在同一逻辑下处理它更快。

如何解决这个问题,我们将不胜感激任何帮助(或新想法)。

4 个答案:

答案 0 :(得分:0)

你的PostgreSQL版本是什么?

无论如何,这就是我想出来的

delete from TABLE1 where
STATUS in ('FILLED','EXPIRED','REJECTED','CANCELLED') or
STATUS in (select STATUS from TABLE1 where STATUS in ('PARTIAL','NEW')
           and VALIDITY!='DAY') OR
STATUS in (select status from TABLE1 where STATUS ='REPLACED'
           and orig_ID not in 
           (select ORig_ID from table1 where status in ('PARTIAL','NEW')))

http://sqlfiddle.com/#!15/9e465/54

答案 1 :(得分:0)

除非我弄错了,否则OP中的输出或逻辑会出错。

DELETE 
FROM TABLE1 AS T
WHERE STATUS IN ('FILLED', 'EXPIRED', 'REJECTED', 'CANCELLED')
  OR ( STATUS IN ('PARTIAL', 'NEW')
      AND VALIDITY NOT IN ('GTD', 'GTC') )
  OR ( STATUS = 'REPLACED'
  AND NOT EXISTS
    (SELECT 1
     FROM TABLE1 tbl1
     WHERE T.ID <> tbl1.ID
       AND T.ORIG_ID = tbl1.ORIG_ID
       AND tbl1.STATUS IN ('PARTIAL', 'NEW')
       AND tbl1.VALIDITY NOT IN ('GTD', 'GTC')
    ) 
  );

http://sqlfiddle.com/#!15/9e465/16

编辑:看来OP意味着

&#34; REPLACED - 除非[它没有GTD / GTC状态]且其他条目具有相同的ORIG_ID&#34;

而不是

&#34; REPLACED - 除非有其他条目具有相同的ORIG_ID [没有GTD / GTC状态]&#34;

答案 2 :(得分:0)

Delete from table1
WHERE status in ('FILLED','EXPIRED','REJECTED','CANCELLED')
OR (status in ('PARTIAL','NEW') AND validity not in ('GTD','GTC'))
OR (status = 'REPLACED' and orig_ID not in 
    (select ORig_ID from table1 where status in ('PARTIAL','NEW')));

http://sqlfiddle.com/#!15/9e465/28/0

答案 3 :(得分:0)

尝试使用此DELETE语句:

DELETE FROM TABLE1 as MASTER 
WHERE 
  STATUS IN ('FILLED', 'EXPIRED', 'REJECTED', 'CANCELLED') OR
  (STATUS IN ('PARTIAL','NEW') AND VALIDITY NOT IN ('GTD','GTC')) OR
  (STATUS='REPLACED' AND ID NOT IN
    (SELECT ORIG_ID FROM TABLE1 OTHER 
      WHERE OTHER.ORIG_ID=MASTER.ID AND 
      STATUS IN ('PARTIAL','NEW') AND VALIDITY IN ('GTD','GTC')));

SQL Fiddle Example(使用SELECT句子)