如何比较两个数据库的差异

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何比较两个数据库的差异相关的知识,希望对你有一定的参考价值。

构建两个临时表,将两个数据库结构信息导入。
create Table #t1
(
ID Int Identity(1,1) Not Null Primary Key,
tablename nvarchar(50) NULL,
columnName nvarchar(50) NULL,
columnIndex int null,
columnType nvarchar(50) NULL
)
use 数据库1
insert into #t1
create Table #t2
(
ID Int Identity(1,1) Not Null Primary Key,
tablename nvarchar(50) NULL,
columnName nvarchar(50) NULL,
columnIndex int null,
columnType nvarchar(50) NULL
)

//开始比较
use 数据库2
insert into #t2
SELECT
SO.name as \'表名\',
SC.name as \'表列名\',
SC.colid as \'索引\',
ST.name as \'类型\'
FROM
sysobjects SO, -- 对象表
syscolumns SC, -- 列名表
systypes ST -- 数据类型表
WHERE
SO.id = SC.id
AND SO.xtype = \'U\' -- 类型U表示表,V表示视图
AND SO.status >= 0 --加一个条件:SO.status >= 0,否则会将系统的临时表显示出来
AND SC.xtype = ST.xusertype
ORDER BY
SO.name, SC.colorder
go

//查询出 在t1 里有, t2 里没有的字段,查询列出来。
select * from
(
select tablename,columnName,columnType from #t1 where tablename like \'%EMS_%\'
EXCEPT
select tablename,columnName,columnType from #t2 where tablename like \'%EMS_%\'
) as c
order by tablename

比较两个数据库中表和字段的差异

-- 比较两个数据库中表的差异
-- u表,p存储过程,v视图
-- INTFSIMSNEW新库,INTFSIMS旧库
SELECT NTABLE = A.NAME, OTABLE = B.NAME
FROM INTFSIMSNEW..SYSOBJECTS A
LEFT JOIN INTFSIMS..SYSOBJECTS B
ON A.NAME = B.NAME
WHERE ISNULL(B.NAME, \'\') = \'\'
AND A.XTYPE = \'U\'

UNION ALL

SELECT NTABLE = B.NAME, OTABLE = A.NAME
FROM INTFSIMS..SYSOBJECTS A
LEFT JOIN INTFSIMSNEW..SYSOBJECTS B
ON A.NAME = B.NAME
WHERE ISNULL(B.NAME, \'\') = \'\'
AND A.XTYPE = \'U\'
ORDER BY 1, 2

-- 比较两个数据库中每个表字段的差异
SELECT
表名A = CASE WHEN ISNULL(A.TABLENAME, \'\') <> \'\' THEN A.TABLENAME ELSE B.TABLENAME END,
字段名A = A.FIELDNAME,
字段名B = B.FIELDNAME,
顺序= A.FIELDSNO,
说明= CASE WHEN A.FIELDTYPE <> B.FIELDTYPE THEN \'类型: \' + A.FIELDTYPE + \'-->\' + B.FIELDTYPE
WHEN A.FIELDSNO <> B.FIELDSNO THEN \'顺序: \' + str(A.FIELDSNO) + \'-->\' + str(B.FIELDSNO)
WHEN A.LENGTH <> B.LENGTH THEN \'长度: \' + str(A.LENGTH) + \'-->\' + str(B.LENGTH)
WHEN A.LENSEC <> B.LENSEC THEN \'小数位: \' + str(A.LENSEC) + \'-->\' + str(B.LENSEC)
WHEN A.ALLOWNULL <> B.ALLOWNULL THEN \'允许空值: \' + str(A.ALLOWNULL) + \'-->\' + str(B.ALLOWNULL)
END
FROM (SELECT
TABLENAME = B.NAME,
FIELDNAME = A.NAME,
FIELDSNO = A.COLID,
FIELDTYPE = C.NAME,
LENGTH = A.LENGTH,
LENSEC = A.XSCALE,
ALLOWNULL = A.ISNULLABLE
FROM INTFSIMSNEW..SYSCOLUMNS A
LEFT JOIN INTFSIMSNEW..SYSOBJECTS B
ON A.ID = B.ID
LEFT JOIN INTFSIMSNEW..SYSTYPES C
ON A.XUSERTYPE = C.XUSERTYPE
WHERE B.XTYPE = \'U\') A
FULL JOIN (SELECT
TABLENAME = B.NAME,
FIELDNAME = A.NAME,
FIELDSNO = A.COLID,
FIELDTYPE = C.NAME,
LENGTH = A.LENGTH,
LENSEC = A.XSCALE,
ALLOWNULL = A.ISNULLABLE
FROM INTFSIMS..SYSCOLUMNS A
LEFT JOIN INTFSIMS..SYSOBJECTS B
ON A.ID = B.ID
LEFT JOIN INTFSIMS..SYSTYPES C
ON A.XUSERTYPE = C.XUSERTYPE
WHERE B.XTYPE = \'U\') B
ON A.TABLENAME = B.TABLENAME
AND A.FIELDNAME = B.FIELDNAME
WHERE ISNULL(A.TABLENAME, \'\') = \'\'
OR ISNULL(B.TABLENAME, \'\') = \'\'
OR A.FIELDTYPE <> B.FIELDTYPE
OR A.FIELDSNO <> B.FIELDSNO
OR A.LENGTH <> B.LENGTH
OR A.LENSEC <> B.LENSEC
OR A.ALLOWNULL <> B.ALLOWNULL
ORDER by 1, 4
参考技术A 什么数据库啊

比较两个熊猫数据框的差异

【中文标题】比较两个熊猫数据框的差异【英文标题】:Comparing two pandas dataframes for differences 【发布时间】:2013-11-23 21:58:07 【问题描述】:

我有一个更新 5-10 列数据的脚本,但有时起始 csv 将与结束 csv 相同,因此我不想编写相同的 csv 文件,而是希望它什么都不做......

如何比较两个数据框以检查它们是否相同?

csvdata = pandas.read_csv('csvfile.csv')
csvdata_old = csvdata

# ... do stuff with csvdata dataframe

if csvdata_old != csvdata:
    csvdata.to_csv('csvfile.csv', index=False)

有什么想法吗?

【问题讨论】:

不是 Pandas 专家,但不应该进行正常的相等比较工作吗? 我已经查看了相等性,但我不确定如何使用该功能,我也无法在搜索中找到任何内容:( 【参考方案1】:

您还需要小心创建 DataFrame 的副本,否则 csvdata_old 将使用 csvdata 更新(因为它指向同一个对象):

csvdata_old = csvdata.copy()

查看是否相等,可以use assert_frame_equal as in this answer:

from pandas.util.testing import assert_frame_equal
assert_frame_equal(csvdata, csvdata_old)

您可以将其包装在一个函数中,例如:

try:
    assert_frame_equal(csvdata, csvdata_old)
    return True
except:  # appeantly AssertionError doesn't catch all
    return False

讨论了更好的方法...

【讨论】:

由于某种原因我得到了异常:Exception: Can only compare identically-labeled DataFrame objects 那给了你答案,对吧?这是说标签(行和列名称/值)不相同,因此 DataFrames 不能相同。在 Andy 的包装器中添加另一个 except 行:except Exception: return False @Hyflex 是的,正如 Tom 指出的那样,只需删除 AssertionError (在它仅在 AssertionError 上停止并引发其他任何事情之前)... 好的,我修复了标签(没有意识到我必须重新排序 csvdat_old 的标签顺序,我尝试将其合并到我的实际数据中,但即使数据相同时它也会更新输出,有没有办法找到/查看究竟是什么“不同”? 如何获取这些帧中的不同值?【参考方案2】:

这会比较两个数据框的,注意表之间的行/列数需要相同

comparison_array = table.values == expected_table.values
print (comparison_array)

>>>[[True, True, True]
    [True, False, True]]

if False in comparison_array:
    print ("Not the same")

#Return the position of the False values
np.where(comparison_array==False)

>>>(array([1]), array([1]))

然后您可以使用此索引信息返回表之间不匹配的值。由于它是零索引的,它指的是第二个位置的第二个数组,这是正确的。

【讨论】:

这里的主要好处是您可以使用 np.where 返回的索引位置来确定表格不匹配的确切位置并提醒用户该位置。【参考方案3】:

不确定在发布问题时这是否存在,但 pandas 现在有一个内置函数来测试两个数据帧之间的相等性:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.equals.html。

【讨论】:

不,从未存在过,它的工作原理也一样好。 (更好,因为它是单行而不是 5 行 它在花车上是如何工作的?我希望有一个精度参数。 肯定有比这更好的东西。只是一个错误不是一个令人满意的答案 不确定这是否是大多数人想要的。DataFrame.equals 进行了非常深入的比较。例如.. 我有 2 个值相等的数据帧.. 但事实证明 DataFrames 也有一些参数称为 Axis 1IntBlockObjectBlock。这些在pd._data 下定义。如果这两个对象之间的这些不相同..它将导致 False @Nickpick DataFrame.eq 可能很适合定位不相等的元素?【参考方案4】:

检查使用:df_1.equals(df_2) # 返回 True 或 False详情如下

In [45]: import numpy as np

In [46]: import pandas as pd

In [47]: np.random.seed(5)

In [48]: df_1= pd.DataFrame(np.random.randn(3,3))

In [49]: df_1
Out[49]: 
          0         1         2
0  0.441227 -0.330870  2.430771
1 -0.252092  0.109610  1.582481
2 -0.909232 -0.591637  0.187603

In [50]: np.random.seed(5)

In [51]: df_2= pd.DataFrame(np.random.randn(3,3))

In [52]: df_2
Out[52]: 
          0         1         2
0  0.441227 -0.330870  2.430771
1 -0.252092  0.109610  1.582481
2 -0.909232 -0.591637  0.187603

In [53]: df_1.equals(df_2)
Out[53]: True


In [54]: df_3= pd.DataFrame(np.random.randn(3,3))

In [55]: df_3
Out[55]: 
          0         1         2
0 -0.329870 -1.192765 -0.204877
1 -0.358829  0.603472 -1.664789
2 -0.700179  1.151391  1.857331

In [56]: df_1.equals(df_3)
Out[56]: False

【讨论】:

有一个问题:index.names 没有进行比较。详情见我的回答:***.com/a/43420842/304209【参考方案5】:

更准确的比较应该单独检查索引名称,因为DataFrame.equals 不会对此进行测试。所有其他属性(索引值(单/多索引)、值、列、dtypes)都由它正确检查。

df1 = pd.DataFrame([[1, 'a'], [2, 'b'], [3, 'c']], columns=['num', 'name'])
df1 = df1.set_index('name')
df2 = pd.DataFrame([[1, 'a'], [2, 'b'], [3, 'c']], columns=['num', 'another_name'])
df2 = df2.set_index('another_name')

df1.equals(df2)
True

df1.index.names == df2.index.names
False

注意:使用index.names 而不是index.name 也可以用于多索引数据帧。

【讨论】:

【参考方案6】:

不确定这是否有用,但我将这个快速的 python 方法组合在一起,只返回两个具有相同列和形状的数据帧之间的差异。

def get_different_rows(source_df, new_df):
    """Returns just the rows from the new dataframe that differ from the source dataframe"""
    merged_df = source_df.merge(new_df, indicator=True, how='outer')
    changed_rows_df = merged_df[merged_df['_merge'] == 'right_only']
    return changed_rows_df.drop('_merge', axis=1)

【讨论】:

这是我真正在寻找的答案。非常感谢 这太棒了!但我可以问它怎么能不忽略数据类型?例如,如果source_df 上有一个值4new_df 上的4.0,它仍然应该返回一个dataframe,因为这意味着存在差异,谢谢! 谢谢你。而且实用功能真的好用!【参考方案7】:

就我而言,我遇到了一个奇怪的错误,即使索引、列名 并且值相同,DataFrames 不匹配。我追踪到 数据类型,似乎pandas 有时可以使用不同的数据类型, 导致这样的问题

例如:

param2 = pd.DataFrame('a': [1]) param1 = pd.DataFrame('a': [1], 'b': [2], 'c': [2], 'step': ['alpha'])

如果你检查param1.dtypesparam2.dtypes,你会发现'a'是 为param1 输入object,为param2 输入int64。现在,如果你这样做 使用param1param2 的组合进行一些操作,其他 数据框的参数将偏离默认参数。

因此,在生成最终数据帧之后,即使实际值 打印出来是一样的,final_df1.equals(final_df2),结果可能是 不相等,因为像Axis 1ObjectBlock 这样的小参数, IntBlock 可能不一样。

解决此问题并比较值的一种简单方法是使用

final_df1==final_df2.

但是,这将逐个元素进行比较,所以如果你 正在使用它来断言例如pytest 中的语句。

TL;DR

效果很好的是

all(final_df1 == final_df2).

这会逐个元素进行比较,同时忽略不包含的参数 比较重要。

TL;DR2

如果您的值和索引相同,但final_df1.equals(final_df2) 显示False,您可以使用final_df1._datafinal_df2._data 检查数据框的其余元素。

【讨论】:

有谁知道为什么从 CSV 读取的数据框与从 Excel 工作簿读取的数据框显示不同,即使它们相同?【参考方案8】:

拉出对称差异:

df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)

例如:

df1 = pd.DataFrame(
    'num': [1, 4, 3],
    'name': ['a', 'b', 'c'],
)
df2 = pd.DataFrame(
    'num': [1, 2, 3],
    'name': ['a', 'b', 'd'],
)

将产生:

注意:在 pandas 的下一个版本之前,为避免将来如何设置 sort 参数的警告,只需添加 sort=False 参数即可。如下:

df_diff = pd.concat([df1,df2], sort=False).drop_duplicates(keep=False)

【讨论】:

【参考方案9】:

希望下面的sn-p代码对你有帮助!

import pandas as pd
import datacompy

df_old_original = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [7, 7, 7, 7], [3, 3, 3, 3], [4, 4, 4, 4], [7, 7, 7, 7], [5, 5, 5, 5], [6, 6, 6, 6]], columns=['A', 'B', 'C', 'D'], index=[0, 1, 2, 3, 4, 5, 6, 7], dtype=object)
df_new_original = pd.DataFrame([[None, None, None, None], [1, 1, 1, 1], [2, 2, 2, 2], [8, 8, 8, 8], [3, 3, 3, 3], [4, 4, 4, 4], [7, 7, 7, 7], [5, 5, 5, 5], [None, None, None, None]], columns=['A', 'B', 'C', 'D'], index=[0, 1, 2, 3, 4, 5, 6, 7, 8], dtype=object)

compare = datacompy.Compare(df_old_original, df_new_original, join_columns=['A', 'B', 'C', 'D'], abs_tol=0, rel_tol=0, df1_name='Old', df2_name='New')
changes_in_old_df = compare.df1_unq_rows
changes_in_new_df = compare.df2_unq_rows
print(changes_in_old_df)
print(changes_in_new_df)
print(Compare.report())

【讨论】:

以上是关于如何比较两个数据库的差异的主要内容,如果未能解决你的问题,请参考以下文章

oracle如何比较两个表数据的差异?

如何在行级别上比较两个海量 Spark 数据帧并打印差异

比较与特定字段有关的两个表之间的差异时如何正确连接

比较两个熊猫数据框的差异

如何在GEO数据库中比较两个子集 我想在两组芯片数据之间比较存在表达差异4倍以上的基因 应该怎么操作

如何比较两组数据的差异性?