我正在使用PostgreSQL。我有一张桌子keywords
:
# Table name: keywords
#
# id :integer not null, primary key
# text :string not null
# match_type :string not null
# adgroup_id :integer not null
表具有唯一索引USING btree (match_type, adgroup_id, text)
现在,问题在于,对于相同的adgroup_id
和match_type
,有"Hello"
和" Hello"
或"Hello "
或" Hello "
之类的文本(请注意前导/尾随空格)。
问题是text
列在字符串的开头和结尾包含那些空格,从而导致错误的数据(如果没有这些空格,则不会通过uniq索引)。
我计划将来在插入之前添加空白修剪,但是首先我需要清理数据。
如何删除留下重复数据的“重复”数据(基于字符串比较 前导和尾随空格)?
答案 0 :(得分:1)
这里是使用CTE的一种选择。 CTE查找具有两个两个或更多(match_type, adgroup_id)
值的所有text
组,这些值与修剪的前导和尾随空白相同。我们还将计算以下内容:
(match_type, adgroup_id)
组的任意行号,从值1开始
然后,仅当行出现在重复组中并且不是纯文本版本(cnt > 0
)或任意行号大于1时,才删除行。这意味着对于情况"Hello "
和" Hello"
,这两个记录之一将被任意删除。但是,如果存在带有"Hello"
的第三条“纯”记录,则将保留该记录,并且前两个案例均将被删除。
with cte as (
select match_type, adgroup_id, trim(text) as text,
count(case when text = trim(text) then 1 end) as cnt,
row_number() over (partition by match_type, adgroup_id order by trim(text)) rn
from keywords
group by match_type, adgroup_id, trim(text)
having count(*) > 1
)
delete
from keywords k1
where exists (select 1 from cte k2
where k1.match_type = k2.match_type and
k1.adgroup_id = k2.adgroup_id and
k1.text <> k2.text and (k2.cnt > 0 or k2.rn > 1));
答案 1 :(得分:1)
demo:db<>dbfiddle (示例包含两个组:“ Hello”不带空格的元素;“ Bye”不带空格的元素)
DELETE FROM keywords
WHERE id NOT IN (
SELECT DISTINCT ON (trim(text)) --1
id
FROM
keywords
ORDER BY
trim(text),
text = trim(text) DESC --2
)
DISTINCT ON
子句采用。如果没有,将采用其他元素包含其他列的解决方案:
DELETE FROM keywords
WHERE id NOT IN (
SELECT DISTINCT ON (match_type, adgroup_id, trim(text))
id
FROM
keywords
ORDER BY
match_type,
adgroup_id,
trim(text),
text = trim(text) DESC
)