【问题标题】:How to find difference between table with multiple conditions如何找到具有多个条件的表之间的差异
【发布时间】:2023-02-06 20:46:32
【问题描述】:

我有两个确切的表,但有些值差异。所以我想找到那些差异,条件是如果列 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 的情况下如何合并这两个查询的结果?我只想有一个查询(可以接受子查询)

【问题讨论】:

  • 你能分享一些数据和预期的输出吗

标签: sql postgresql


【解决方案1】:

在您的第一个查询中,您可以替换特定数字的空值。像这样:

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

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

【讨论】:

  • PostgreSQL 中没有isnull()。您可以将其替换为 coalesce(m.value,-99)case when m.value is null then -99 end
【解决方案2】:

假设在给定的一天,您需要找到

  • 表之间匹配但超过 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

【讨论】:

  • 感谢您的答复。结合我的意思是,结合上述查询的两个输出的结果。第一个查询返回具有给定列的匹配记录。但是我过滤掉了值差异超过 10 的记录。因此,如果所有列值都匹配但值之间的差异是 11,我想在最终结果中看到它。而第二个查询返回所有在列中有差异的行。所以我想在不使用 UNION 的情况下合并这两个查询的结果。带有子查询的首选 1 查询。我执行了您的查询,结果为值列为 NULL。
  • @Miko 我设置了一个test 并通过查看您的查询行为弄清楚了您的意思:您似乎正在寻找(表之间匹配但超过值差异阈值的行)和(存在的行在左表或右表中,在另一个表中没有对应的行)。我更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
相关资源
最近更新 更多