我有一张大桌子,我需要检查类似的行。我不需要所有的列值都一样,只要相似即可。这些行不能“相隔很远”(由对其他表的查询确定),没有值可能太过不同(我已经针对这些条件进行了查询),并且大多数其他值必须相同。我必须期待一些歧义,所以一个或两个不同的值不应破坏“相似性”(好吧,我可以通过仅接受“完全相等”的行来获得更好的性能,但是这种简化可能会导致错误;我将这样做是因为选项)。
我要解决的方法是通过PL / pgSQL:对先前查询的结果进行FOR LOOP迭代。对于每一列,我都会进行IF测试,以了解是否有所不同。如果是,我增加一个差计数器并继续。在每个循环的最后,我将值与阈值进行比较,看看是否应将行保持为“相似”。
与纯SQL查询或包含某些PL / pgSQL函数的SQL查询相比,这种PL / pgSQL繁重的方法看起来很慢。如果我知道哪些行应该不同,那么测试除X个等效行外的所有行将很容易,但是在大约40行中的任何行上都可能出现差异。有什么方法可以通过单个查询解决此问题吗?如果不是,是否有比检查所有行更快的方法?
编辑:我提到了一个表,实际上它是一组由1:1关系链接的六个表。我不想解释什么是什么,这是一个不同的问题。从一张桌子上做这个到我的情况对我来说很容易。因此,我简化了它(但没有过分简化-它应该证明我在那里遇到的所有困难),并举例说明了我的需要。空值和其他任何内容都应视为“不同”。无需编写脚本来测试所有内容-我只需要找出是否有可能以比我想象的更有效的方式进行操作。
关键是我不需要像往常一样对行进行计数,而只需对列进行计数。
EDIT2:之前的小提琴-并不是很短,所以我出于存档的原因而在这里。
EDIT3:此处为简化示例-只是NOT NULL整数,省略了预处理。数据的当前状态:
select * from foo;
id | bar1 | bar2 | bar3 | bar4 | bar5
----+------+------+------+------+------
1 | 4 | 2 | 3 | 4 | 11
2 | 4 | 2 | 4 | 3 | 11
3 | 6 | 3 | 3 | 5 | 13
当我运行时select similar_records( 1 );
,我应该只获得第2行(2列具有不同的值;这在限制之内),而不是3(4个不同的值-最多在两个差的限制之外)。
要查找仅在给定的最大列数上不同的行:
WITH cte AS (
SELECT id
,unnest(ARRAY['bar1', 'bar2', 'bar3', 'bar4', 'bar5']) AS col -- more
,unnest(ARRAY[bar1::text, bar2::text, bar3::text
, bar4::text, bar5::text]) AS val -- more
FROM foo
)
SELECT b.id, count(a.val <> b.val OR NULL) AS cols_different
FROM (SELECT * FROM cte WHERE id = 1) a
JOIN (SELECT * FROM cte WHERE id <> 1) b USING (col)
GROUP BY b.id
HAVING count(a.val <> b.val OR NULL) < 3 -- max. diffs allowed
ORDER BY 2;
我忽略了您问题中所有其他令人分心的细节。
用5列进行演示。根据需要添加更多。
如果可以NULL
使用column,则可能要使用IS DISTINCT FROM
而不是<>
。
这是使用有点非常规但很方便的parallelunnest()
。两个数组必须具有相同数量的元素才能工作。细节:
SQL Fiddle(在您的基础上构建)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句