2016-12-02 83 views
0

我想编写一个函数,在postgresql的指定列中标记重复项。在查询中标记重复项的函数Postgresql

举例来说,如果我有如下表:

country | landscape | household 
-------------------------------- 
TZA  | L01  | HH02 
TZA  | L01  | HH03 
KEN  | L02  | HH01 
RWA  | L03  | HH01 

我想能够运行下面的查询:

SELECT country, 
     landscape, 
     household, 
     flag_duplicates(country, landscape) AS flag 
FROM mytable 

,并得到以下结果:

country | landscape | household | flag 
--------------------------------------- 
TZA  | L01  | HH02  | duplicated 
TZA  | L01  | HH03  | duplicated 
KEN  | L02  | HH01  | 
RWA  | L03  | HH01  | 

在函数体内部,我想我需要类似于:

IF (country || landscape IN (SELECT country || landscape FROM mytable 
          GROUP BY country || landscape) 
    HAVING count(*) > 1) THEN 'duplicated' 
ELSE NULL 

但我很困惑如何通过所有这些作为参数。我很感激帮助。我正在使用postgresql版本9.3。

回答

1

你不需要一个功能来完成。因为性能,对结果集中的每一行使用函数并不是一个好主意。一种更好的解决方案是使用纯SQL(即使是使用子查询),并为数据库引擎提供优化它的机会。在你的例子中,它应该是这样的:

SELECT t.country,t.landscape,t.household,case when duplicates.count>1 then 'duplicate'end 
FROM mytable t JOIN ( 
SELECT count(household) FROM mytable GROUP BY country,landscape 
) duplicates ON duplicates.country=t.country AND duplicates.landscape=t.landscape 

它产生完全相同的结果。

更新 - 如果要不惜一切代价来使用功能,这里是工作示例:

CREATE FUNCTION find_duplicates(arg_country varchar, arg_landscape varchar) returns varchar AS $$ 
BEGIN 
    RETURN CASE WHEN count(household)>1 THEN 'duplicated' END FROM mytable 
    WHERE country=arg_country AND landscape=arg_landscape 
    GROUP BY country,landscape; 
END 
$$ 
LANGUAGE plpgsql STABLE; 
0
select 
    *, 
    (count(*) over (partition by country, landscape)) > 1 as flag 
from 
    mytable; 

对于功能看@MarcinH answer但增加stable到函数的定义,以使其调用更快。