使用每个函数的一列比较两个 table 函数的结果

Compare result of two table functions using one column from each

根据说明 here 我创建了两个函数,它们使用 EXECUTE FORMAT 和 return 与 (int,smallint) 相同的 table。

示例定义:

CREATE OR REPLACE FUNCTION function1(IN _tbl regclass, IN _tbl2 regclass, 
IN field1 integer) 
RETURNS TABLE(id integer, dist smallint)

CREATE OR REPLACE FUNCTION function2(IN _tbl regclass, IN _tbl2 regclass, 
IN field1 integer) 
RETURNS TABLE(id integer, dist smallint)

两个函数 return 行数完全相同。示例结果( 将始终按 dist 排序):

(49,0)
(206022,3)
(206041,3)
(92233,4)

有没有办法比较相同行的两个函数之间第二个字段的值,以确保两个结果相同:

例如:

SELECT
function1('tblp1','tblp2',49),function2('tblp1_v2','tblp2_v2',49)

Returns 类似于:

(49,0)      (49,0)
(206022,3)  (206022,3)
(206041,3)  (206041,3)
(92233,4)   (133,4)

虽然我不期待相同的结果(每个函数都是一个 topK 查询,我有任意打破的关系/在第二个函数中进行一些优化以获得更快的性能)我可以确保两个函数 return 正确的结果,如果对于每一行,结果中的第二个数字是相同的。在上面的示例中,我可以确保得到正确的结果,因为:

1st row 0 = 0,
2nd row 3 = 3,
3rd row 3 = 3,
4th row 4 = 4

尽管对于第 4 行,92233!=133

有没有办法只获取每个函数结果的第二个字段,以批量比较它们,例如像这样的东西:

SELECT COUNT(*)
FROM 
(SELECT
function1('tblp1','tblp2',49).field2,
function2('tblp1_v2','tblp2_v2',49).field2 ) n2
WHERE  function1('tblp1','tblp2',49).field2 != function1('tblp1','tblp2',49).field2;

我正在使用 PostgreSQL 9.3。

不保证从函数中 return 编辑行的顺序。如果您可以从函数中 return row_number()(下例中的 rn),则:

select
    count(f1.dist is null or f2.dist is null or null) as diff_count
from
    function1('tblp1','tblp2',49) f1
    inner join
    function2('tblp1_v2','tblp2_v2',49) f2 using(rn)

Is there a way to get only the 2nd field of each function result, to batch compare them?

以下所有答案均假定行以 匹配 顺序返回。

Postgres 9.3

利用从 SRF 函数中分解行的古怪功能返回 相同 并行行数:

SELECT count(*) AS mismatches
FROM  (
   SELECT function1('tblp1','tblp2',49) AS f1
        , function2('tblp1_v2','tblp2_v2',49) AS f2
   ) sub
WHERE  (f1).dist <> (f2).dist;  -- note the parentheses!

行类型两边的括号是消除可能的 table 引用的歧义所必需的。 Details in the manual here.

如果返回的行数不同(这会完全破坏它),则默认为行的笛卡尔积。

Postgres 9.4

WITH ORDINALITY 即时生成行号

您可以使用 WITH ORDINALITY 即时生成行号,不需要依赖 SELECT 列表中 SRF 函数的结果配对:

SELECT count(*) AS mismatches
FROM      function1('tblp1','tblp2',49)       WITH ORDINALITY AS f1(id,dist,rn)
FULL JOIN function2('tblp1_v2','tblp2_v2',49) WITH ORDINALITY AS f2(id,dist,rn) USING (rn)
WHERE  f1.dist IS DISTINCT FROM f2.dist;

这适用于每个函数的相同行数以及不同的数字(这将被视为不匹配)。

相关:

  • PostgreSQL unnest() with element number

ROWS FROM 逐行加入集合

SELECT count(*) AS mismatches
FROM   ROWS FROM (function1('tblp1','tblp2',49)
                , function2('tblp1_v2','tblp2_v2',49)) t(id1, dist1, id2, dist2)
WHERE  t.dist1 IS DISTINCT FROM t.dist2;

相关回答:

旁白:
EXECUTE FORMAT 不是一组 plpgsql 功能。 RETURN QUERY 是。 format()只是一个构建查询字符串的方便函数,可以在SQL或plpgsql中的任何地方使用。

供日后参考:

检查行数差异:

SELECT 
ABS(count(f1a.*)-count(f2a.*))  
FROM
(SELECT f1.dist, row_number()  OVER(ORDER BY f1.dist) rn
FROM
function1('tblp1','tblp2',49) f1)
f1a FULL JOIN 

(SELECT f2.dist, row_number() OVER(ORDER BY f2.dist) rn
FROM
function2('tblp1_v2','tblp2_v2',49) f2) f2a
USING (rn);

检查相同排序行的 dist 差异:

SELECT 
COUNT(*)  

FROM

(SELECT f1.dist, row_number()  OVER(ORDER BY f1.dist) rn
FROM
function1('tblp1','tblp2',49) f1)
f1a 
(SELECT f2.dist, row_number() OVER(ORDER BY f2.dist) rn
FROM
function2('tblp1_v2','tblp2_v2',49) f2) f2a
WHERE f1a.rn=f2a.rn
AND f1a.distance <> f2a.distance;

一个简单的 OVER() 也可能有效,因为函数的结果已经排序但被添加以进行额外检查。