【问题标题】:database - method of comparing 2 keyless tables数据库 - 比较 2 个无键表的方法
【发布时间】:2011-10-06 11:19:03
【问题描述】:

我正在尝试研究如何比较两个应该具有完全相同数据的无键(即,没有列是主键或唯一的)表。即 tablea 从 my_schema1 到 my_schema2 的直接迁移。

我在想一种可能的方法是:

IF 
    count from 
    ((select * from my_schema1.tablea
    union
    select * from my_schema2.tablea))
    =
    count from
    ((select * from my_schema1.tablea
    union all
    select * from my_schema2.tablea) / 2)
 THEN
     --both tables would be identical (in record counts and all column values the same)
 ELSE
     --this means that the 2 tables are different in some way
 END IF

很高兴拥有功能:我希望通过消除指定列的需要使解决方案尽可能通用。

【问题讨论】:

  • 由于没有 PK 可能存在重复的行。您希望这些人如何处理?
  • 只要两个表有相同的重复行就可以了。但是,我想确定一个表有一些重复行而另一个表没有的情况。
  • 您当前的查询将因此而失败。如果一个表有一列 C 并且只有 2 行都具有相同的值,则 union 将返回 1 行但 union all 4 行。
  • @KevinBurton - 您的回答不会按要求处理重复项。
  • @KevinBurton - 不,它没有。它只是检查两个表是否具有相同数量的欺骗。不一定是一样的。例如,如果一个表的值 1,1,2 和另一个 1,2,2

标签: sql database oracle comparison


【解决方案1】:
select count(*) 
from 
(
 ( select * from my_schema1.tablea 
   minus 
   select * from my_schema2.tablea
 )
 union 
 ( select * from my_schema2.tablea 
   minus 
   select * from my_schema1.tablea
 )
)

if count(*) = 0 then 
 THEN
     --both tables are identical 
 ELSE
     -- the 2 tables are different in some way
 end if;

【讨论】:

  • 如果table1有一行重复了几次,但它只在table2中出现过一次,这将显示为匹配。
【解决方案2】:

如果你没有重复,你可以这样做......

SELECT
  (SELECT COUNT(*) FROM (SELECT * FROM table1 UNION SELECT * FROM table2)) AS unioned,
  (SELECT COUNT(*) FROM table1)                                            AS table1,
  (SELECT COUNT(*) FROM table2)                                            AS table2

如果两个表匹配,则所有三个数字都应该相同。


如果有重复,可以使用相同的方法,通过添加计数字段...

WITH
  table1 AS (SELECT a, b, c, d, COUNT(*) AS duplicates FROM table1 GROUP BY a, b, c, d),
  table2 AS (SELECT a, b, c, d, COUNT(*) AS duplicates FROM table2 GROUP BY a, b, c, d)
SELECT
  (SELECT COUNT(*) FROM (SELECT * FROM table1 UNION SELECT * FROM table2)) AS unioned,
  (SELECT COUNT(*) FROM table1)                                            AS table1,
  (SELECT COUNT(*) FROM table2)                                            AS table2

【讨论】:

  • 运行时我得到 ORA-00911
【解决方案3】:

假设下面有一列C。您需要将其扩展为完整的列列表(未在 Oracle 上测试,因此可能存在一些小的语法问题,但一般方法应该有效)

WITH T1 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY C ORDER BY C) AS RN
FROM T              
), T2 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY C ORDER BY C) AS RN
FROM T       
), T3 AS
(
SELECT * FROM T1 
MINUS
SELECT * FROM T2
), T4 AS
(
SELECT * FROM T2 
MINUS
SELECT * FROM T1
)
SELECT * FROM T3
UNION ALL 
SELECT * FROM T4

【讨论】:

  • 如果我想扩展到多个列,我会像这样更改这些:PARTITION BY C, no2col, no3col ORDER BY C, no2col, no3col 吗?有没有办法在不指定任何列名的情况下做到这一点?
  • @toop - 第一部分是的,第二部分想不出任何办法。
  • 运行时我得到 ORA-00911。不确定你是否可以用 row_number() 做 *。
  • * 在哪里?在PARTITION BYORDER BY?如果是这样,不,你不能。您需要列出列。但正如我所说,这在 Oracle 中完全未经测试,可能需要调整。不过,这种方法应该可行。
  • @toop - 应该可以。不过,很可能我对 CTE 的使用对于 Oracle 是不正确的。您需要弄清楚 Oracle 的正确语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多