使用"使用"关于多个查询的声明?

时间:2015-04-07 19:17:46

标签: sql postgresql

我试图从我的表中删除重复的行,例如,如果我的customer表包含以下内容:

first_name    last_name    email 
fred          wilford      wilford@xchange.co.uk
fred          wilford      wilford@xchange.co.uk
Damian        Jones        jones@xchange.co.uk

理想的结果应该如下:

first_name    last_name    email 
fred          wilford      wilford@xchange.co.uk
Damian        Jones        jones@xchange.co.uk

对于在删除主表中的重复项之前创建的包含重复行的中间表,并且最后将中间表中的所有行重新插入主表,这应该相当简单。但是我宁愿删除中间表,只是使用类似于with语句的东西。 请考虑以下示例:

with dups as 
(
    select name,last_name,email from customer group by 1,2,3 having  
    count(*) > 1 
)
delete from customer
using
(
    select name,last_name,email from customer group by 1,2,3 having     
    count(*) > 1 
)b
where b.name = customer.name;
insert into customer
(
    select name,last_name,email from dups
)

问题是最终的插入语句失败了,因为" dups"不被承认。有没有办法来解决这个问题?提前致谢

3 个答案:

答案 0 :(得分:3)

如果您愿意,可以chain the CTE

WITH dups AS
(
    select name,last_name,email from customer group by 1,2,3 having  
    count(*) > 1 
),
del AS(
    DELETE FROM customer USING dups WHERE dups.name = customer.name RETURNING dups.*
),
ins AS(
    INSERT INTO customer(name,last_name,email) SELECT name,last_name,email FROM del RETURNING del.*
)
SELECT * FROM ins;

答案 1 :(得分:2)

您也可以这样做:

架构:

create table tbl (first_name varchar(50),
                  last_name varchar(50),    
                  email  varchar(50));
insert into tbl values
('fred','wilford','wilford@xchange.co.uk'),
('fred','wilford','wilford@xchange.co.uk'),
('Damian','Jones','jones@xchange.co.uk');

做到这一点:

CREATE TABLE temp (first_name varchar(50),
                  last_name varchar(50),    
                  email  varchar(50));
INSERT INTO temp SELECT DISTINCT * FROM tbl;
DROP TABLE tbl;
ALTER TABLE temp RENAME TO tbl;

检查:

select * from tbl;

结果:

first_name  last_name   email
fred        wilford     wilford@xchange.co.uk
Damian      Jones       jones@xchange.co.uk

答案 2 :(得分:0)

您可以创建WITH作为临时表,而不是dups子句:

CREATE TEMP TABLE dups (name, last_name, email ) AS
(
    select name,last_name,email from customer group by 1,2,3 having  
    count(*) > 1 
);