我正在使用PostgreSQL 9.2.4。
我有一个带有ID的表和某种类型的第二列。我们称之为X
类型。我还有一个二进制函数,它在一对X
s上运行并返回一个布尔值。我们将此函数称为f
。 f
是传递性的;即,如果f(a,b)
和f(b,c)
都返回true,那么f(a,c)
也是如此。
我想要做的是获取一组ID,第二列的所有对都为此二进制函数返回true。我怎么能做到这一点?
表现不是一个大问题;这是导入过程的一部分,每年只会运行一次。在导入过程中,数据库将不会被使用。
我已经创建了一个SQL Fiddle来开始工作:http://sqlfiddle.com/#!12/57b97/3。我想通过f
函数的结果来收集ID。请注意,一般情况下,f
可能会更复杂。这只是一个例子。
我正在寻找的这个示例SQL Fiddle的输出类似于以下内容:
{1,3,6}
{2,4}
例如,假设我们从一组中选择任意一对ID。假设我们选择1
和3
。然后SELECT f((SELECT data FROM temp WHERE id = 1), (SELECT data FROM temp WHERE id = 3));
返回true。
5
没有显示在任何地方,因为'green'
是唯一一个长度为5的字符串。如果我重新获得副本,那就没关系了。我可以弄清楚如何清理它们。
实际上,我的“第二列”是PostGIS GEOMETRY(LINESTRING)
,而我的“二元功能”是ST_Equals
。所以,我正在寻找一堆重复的线串。我不认为这些信息与手头的问题有关,除了显示我无法简化问题以便更容易处理操作。
答案 0 :(得分:1)
开始摆弄这个SQL Fiddle
select
t1.id id1,
t1.data data1,
t2.id id2,
t2.data data2,
f(t1.data, t2.data) f
from
temp t1
inner join
temp t2 on t1.id < t2.id
order by t1.id, t2.id
然后转到最终版本SQL Fiddle
select array[id1] || array_agg(id2) id2
from (
select t1.id id1, t2.id id2
from
temp t1
inner join
temp t2 on t1.id < t2.id
where f(t1.data, t2.data)
) s
group by id1
order by id1, id2
答案 1 :(得分:0)
在与Clodoaldo Neto的回答一段时间之后,我终于明白了。
WITH matches AS (
select t1.id id1, t2.id id2
from temp t1
inner join temp t2 on t1.id < t2.id
where f(t1.data, t2.data)
)
SELECT id1 || ARRAY_AGG(id2)
FROM matches
WHERE id1 NOT IN (SELECT DISTINCT id2 FROM matches)
GROUP BY id1
SQL小提琴:http://sqlfiddle.com/#!12/57b97/14
CTE直接来自Clodoaldo Neto的内部询问。这非常好,因为它还允许我拆分它们并且如果我想要的话,它具有最低的ID:
WITH matches AS (select t1.id id1, t2.id id2
from temp t1
inner join temp t2 on t1.id < t2.id
where f(t1.data, t2.data)
)
SELECT id1, ARRAY_AGG(id2) AS duplicates
FROM matches
WHERE id1 NOT IN (SELECT DISTINCT id2 FROM matches)
GROUP BY id1