如何进行查询以返回PostgreSQL

时间:2016-10-24 15:09:03

标签: sql postgresql postgresql-9.3

我需要返回两个表之间的差异。

创建临时表

CREATE TEMP TABLE first(
  zoom smallint NOT NULL,
  x integer NOT NULL,
  y integer NOT NULL
);

CREATE TEMP TABLE second(
  zoom smallint NOT NULL,
  x integer NOT NULL,
  y integer NOT NULL
);

插入数据

INSERT INTO first(zoom,x,y) VALUES(5,2,25);
INSERT INTO first(zoom,x,y) VALUES(5,4,45);
INSERT INTO first(zoom,x,y) VALUES(5,7,34);
INSERT INTO first(zoom,x,y) VALUES(5,45,40);
INSERT INTO first(zoom,x,y) VALUES(5,72,63);
INSERT INTO second(zoom,x,y) VALUES(5,2,25);
INSERT INTO second(zoom,x,y) VALUES(5,4,45);
INSERT INTO second(zoom,x,y) VALUES(5,7,34);

通缉结果:

In table first there are extra rows:
5,45,40
5,72,63

修改

对此感到抱歉,但我现在已经知道我的原始数据比我提供的样本复杂得多。因此在原始数据中,表首先包含900行,而第9行包含935行。我假设每个表中的行是不同的,但是我现在不确定,所以我想在查询中包含这个条件。我假设查询将返回35行作为差异,因为我非常确信所有zoom / x / y除了这35之外都是相同的。但是,现在可能就是这种情况。基本上我需要知道的是两个表之间的区别是什么,无论哪种方法最好解决它。

我可以得到这样的东西:

 zoom | x  | y  | first |second
------+----+--- +-------+------
   5  | 45 | 40 |  yes  |  no |

首先是肯定,第二个没有

 zoom | x  | y  | first |second
------+----+--- +-------+------
   5  | 45 | 40 |  yes  |  no |
   5  | 45 | 40 |  yes  |  no |
   5  | 45 | 40 |  yes  |  no |

然后先是否,第二个是

 zoom | x  | y  | first |second
------+----+--- +-------+------
   5  | 45 | 40 |  no   |  yes |
   5  | 45 | 40 |  no   |  yes |
   5  | 45 | 40 |  no   |  yes |

4 个答案:

答案 0 :(得分:2)

您可以使用EXCEPT

select zoom,x,y from first 
except 
select zoom,x,y from second

或者我在这里遗漏了什么

如果您想要两个表中的非匹配记录,那么

select * from
(
select zoom,x,y from first 
except 
select zoom,x,y from second
) a
union all
select * from 
(
select zoom,x,y from second
except 
select zoom,x,y from first 
) b

答案 1 :(得分:1)

这是一种方法:

select max(which) as AppearsIn, x, y, zoom
from ((select 'first' as which, x, y, zoom from first) union all
      (select 'second', x, y, zoom from second)
     ) x
group by x, y, zoom
having count(*) = 1;

这假设每个表中的行是不同的。

答案 2 :(得分:1)

如果要比较两个表的所有列,可以在所有列上使用完全外连接,并检查其中一列是否为:

select case 
          when f.zoom is null then 'missing in first'
          when s.zoom is null then 'missing in second'
       end as status, 
       zoom, x, y
from "first" f
  full outer join second s using (zoom, x, y)
where f.zoom is null or s.zoom is null;

基于using()的联接将返回那些非空的列(并且只返回那些列 - 从结果中删除重复的列)

使用问题中的样本数据时,结果如下:

status            | zoom | x  | y 
------------------+------+----+---
missing in second |    5 | 45 | 40
missing in second |    5 | 72 | 63

如果添加了第二个表中第一个中不存在的行,例如:

 INSERT INTO second(zoom,x,y) VALUES(15,7,34);

然后结果将是:

status            | zoom | x  | y 
------------------+------+----+---
missing in second |    5 | 45 | 40
missing in second |    5 | 72 | 63
missing in first  |   15 |  7 | 34

答案 3 :(得分:1)

如果您还想要可能的重复不匹配,您应该计算它们:

SELECT COALESCE(f.zoom,s.zoom) AS zoom
        , COALESCE(f.x,s.x) AS x
        , COALESCE(f.y,s.y) AS y
        , COALESCE(f.fcnt,0) AS fcnt
        , COALESCE(s.scnt,0) AS scnt
FROM ( SELECT DISTINCT zoom,x,y
        , COUNT (*) AS fcnt
        FROM first
        GROUP BY zoom,x,y
        ) f
FULL OUTER JOIN ( SELECT DISTINCT zoom,x,y
        , COUNT (*) AS scnt
        FROM second
        GROUP BY zoom,x,y
        ) s USING (zoom,x,y)
WHERE f.fcnt IS NULL OR s.scnt IS NULL
        ;