【问题标题】:querying 2 tables with the same spec for the differences查询 2 个具有相同规格的表以查找差异
【发布时间】:2010-09-07 01:20:31
【问题描述】:

我最近不得不解决这个问题,发现我过去多次需要这个信息,所以我想我会发布它。假设下表定义为 def,您将如何编写查询来查找两者之间的所有差异?

表格定义:

CREATE TABLE feed_tbl
(
code varchar(15),
name varchar(40),
status char(1),
update char(1)
CONSTRAINT feed_tbl_PK PRIMARY KEY (code)

CREATE TABLE data_tbl
(
code varchar(15),
name varchar(40),
status char(1),
update char(1)
CONSTRAINT data_tbl_PK PRIMARY KEY (code)

这是我的解决方案,作为使用由联合连接的三个查询的视图。指定的diff_type 是记录需要更新的方式:从_data(2) 中删除,在_data(1) 中更新,或添加到_data(0)

CREATE VIEW delta_vw AS (
SELECT     feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 0 as diff_type
FROM         feed_tbl LEFT OUTER JOIN
                      data_tbl ON feed_tbl.code = data_tbl.code
WHERE     (data_tbl.code IS NULL)

UNION

SELECT     feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 1 as diff_type
FROM         data_tbl  RIGHT OUTER JOIN
                      feed_tbl ON data_tbl.code = feed_tbl.code
where (feed_tbl.name <> data_tbl.name) OR
(data_tbl.status <> feed_tbl.status) OR
(data_tbl.update <> feed_tbl.update) 


UNION

SELECT     data_tbl.code, data_tbl.name, data_tbl.status, data_tbl.update, 2 as diff_type
FROM         feed_tbl LEFT OUTER JOIN
                      data_tbl ON data_tbl.code = feed_tbl.code
WHERE     (feed_tbl.code IS NULL)

)

【问题讨论】:

    标签: sql


    【解决方案1】:

    UNION 将删除重复项,因此只需将两者联合起来,然后搜索包含多个条目的任何内容。给定“代码”作为主键,你可以说:

    edit 0:修改为包含 PK 字段本身的差异

    编辑 1:如果您在现实生活中使用它,请务必列出实际的列名。不要使用点星,因为 UNION 操作要求结果集具有完全匹配的列。如果您从其中一个表中添加/删除一列,此示例将中断。

    select dt.*
    from
      data_tbl dt
     ,( 
      select code
      from
        (        
        select * from feed_tbl
        union
        select * from data_tbl        
        )
      group by code
      having count(*) > 1    
      ) diffs  --"diffs" will return all differences *except* those in the primary key itself 
    where diffs.code = dt.code
    union  --plus the ones that are only in feed, but not in data
    select * from feed_tbl ft where not exists(select code from data_tbl dt where dt.code = ft.code)
    union  --plus the ones that are only in data, but not in feed
    select * from data_tbl dt where not exists(select code from feed_tbl ft where ft.code = dt.code)
    

    【讨论】:

      【解决方案2】:

      我会在第二个 union 中使用一个小的变化:

      where (ISNULL(feed_tbl.name, 'NONAME') <> ISNULL(data_tbl.name, 'NONAME')) OR
      (ISNULL(data_tbl.status, 'NOSTATUS') <> ISNULL(feed_tbl.status, 'NOSTATUS')) OR
      (ISNULL(data_tbl.update, '12/31/2039') <> ISNULL(feed_tbl.update, '12/31/2039')) 
      

      由于我一直不明白的原因,NULL 不等于 NULL(至少在 SQL Server 中)。

      【讨论】:

        【解决方案3】:

        您还可以在diff_type 列上使用FULL OUTER JOINCASE ... END 语句以及querying 2 tables with the same spec for the differences 中的上述where 子句

        这可能会获得相同的结果,但在一个查询中。

        【讨论】:

          猜你喜欢
          • 2016-07-20
          • 1970-01-01
          • 2021-10-08
          • 1970-01-01
          • 2016-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多