postgresql 如何查找多条件表之间的差异

5anewei6  于 2023-02-08  发布在  PostgreSQL
关注(0)|答案(2)|浏览(180)

我有两个完全相同的表,但有一些值的差异。所以我想找到这些差异的条件是,如果列value有一个超过10的差异。
例如,两个表中的所有9列都具有相同的值,但值列之间的差值为11,因此该记录不同。如果值差值为9,则记录相同。
所以我写了这个查询来获取差异:

select * 
from  test.test m 
inner join test.test1 t 
    on
m.month_date = t.month_date and  
m.level_1 = t.level_1 and
m.level_2 = t.level_2 and 
m.level_3 = t.level_3 and 
m.level_4 = t.level_4 and 
m.level_header = t.level_header and 
m.unit = t.unit and 
m.model_type_id = t.model_type_id and 
m.model_version_desc = t.model_version_desc 

where m.month_date = '2022-11-01' and abs(m.value - t.value)  > 10)

因此,这将返回所有列值都匹配但未通过值差条件的所有记录。
其次,我使用完全外部连接来获取所有差异

select  *
from  test.test m 
full outer join test.test1 t 
    on
m.month_date = t.month_date and  
m.level_1 = t.level_1 and
m.level_2 = t.level_2 and 
m.level_3 = t.level_3 and 
m.level_4 = t.level_4 and 
m.level_header = t.level_header and 
m.unit = t.unit and 
m.model_type_id = t.model_type_id and 
m.model_version_desc = t.model_version_desc 

where m.month_date is null  or t.month_date is null and  m.month_date = '2022-11-01'

我如何在没有UNION的情况下合并这两个查询的结果?我只想有一个查询(子查询是可以接受的)

3ks5zfa0

3ks5zfa01#

假设对于给定的一天,你需要找到

  • 表之间匹配但超过value差异阈值的行
    • 和**
  • 行出现在左表或右表中,但在另一个表中没有对应的行
select  *
from  test.test m 
    full outer join test.test1 t 
        using (
         month_date,
         level_1,
         level_2, 
         level_3, 
         level_4, 
         level_header, 
         unit, 
         model_type_id, 
         model_version_desc )
where (m.month_date is null
       or    t.month_date is null
       and   m.month_date = '2022-11-01'  )
or    (m.month_date = '2022-11-01' and abs(m.value - t.value)  > 10);

Online demo
因为用于连接表的列具有相同的名称,所以可以通过将冗长的table1.column1=table2.column1 and...对列表替换为单个USING (month_date,level_1,level_2,level_3,...)(doc)来缩短它们的列表。作为额外好处,它将避免在输出中列出两次匹配列,一次用于左表,一次用于右表。

select * 
from (select 1,2,3) as t1(a,b,c)
    full outer join 
     (select 1,2,3) as t2(a,b,c)
        on t1.a=t2.a 
        and t1.b=t2.b 
        and t1.c=t2.c;
-- a | b | c | a | b | c
-----+---+---+---+---+---
-- 1 | 2 | 3 | 1 | 2 | 3

select * 
from (select 1,2,3) as t1(a,b,c)
    full outer join 
     (select 1,2,3) as t2(a,b,c)
        using(a,b,c);
-- a | b | c
-----+---+---
-- 1 | 2 | 3
cld4siwp

cld4siwp2#

在第一个查询中,您可以替换特定数字的空值,如下所示:

where m.month_date = '2022-11-01' and abs(ISNULL(m.value,-99) - ISNULL(t.value,-99))  > 10)

以上代码将替换-99的空值(为您的数据选择一个合适的值),因此如果m.值为10,t.值为空,则在第一次查询中应返回。

相关问题