还有一个替代示例:
-- Test table
CREATE TABLE dummy_data (
author_id int,
message text
);
-- Test data
INSERT INTO dummy_data ( author_id, message )
VALUES
( 123, '"message!"' ),
( 123, '"message!"' ),
( 123, '"different message"' ),
( 124, '"message!"' ),
( 124, '"message!"' ),
( 125, '"message!"' );
-- Delete query
DELETE FROM dummy_data
WHERE ctid NOT IN (
SELECT max( ctid )
FROM dummy_data
GROUP BY message -- this is important to specify
)
-- just for test returning deleted records,
-- you may ignore it, if don't want
RETURNING *;
-- Confirming result:
SELECT * FROM dummy_data ;
author_id | message
-----------+---------------------
123 | "different message"
125 | "message!"
(2 rows)
查看有关系统列的更多信息:https://www.postgresql.org/docs/current/static/ddl-system-columns.html
编辑:
要求通过 ID (author_id) 限制范围的附加示例。
纯查询:
DELETE FROM dummy_data
USING ( SELECT ARRAY[ 123, 124] ) v(id)
WHERE author_id = ANY ( v.id )
AND ctid NOT IN (
SELECT max( ctid )
FROM dummy_data
WHERE author_id = ANY ( v.id )
GROUP BY message
);
与 cmets 相同的查询:
DELETE FROM dummy_data
-- Add your 'author_id' values into array here.
-- Reason we list it here with USING statement is
-- because we need to compare values in two places
-- and if list is too big it would be annoyance to
-- write it 2 times :)
USING ( SELECT ARRAY[ 123, 124] ) v(id)
-- First we get all the authors in the batch by ID
WHERE author_id = ANY ( v.id )
-- Secondly we get max CTID to ignore using same
-- authors range in batch scope
AND ctid NOT IN (
SELECT max( ctid )
FROM dummy_data
WHERE author_id = ANY ( v.id )
GROUP BY message
);
-- This will delete following rows:
author_id | message
-----------+------------
123 | "message!"
123 | "message!"
124 | "message!"
(3 rows)
-- Leaving the state to table:
author_id | message
-----------+---------------------
123 | "different message"
124 | "message!"
125 | "message!"
(3 rows)