我见过一些方法,我如何比较(compare_df,dplyr等(,它们足够有效。但是,当我想比较大或巨大的数据帧时,我得到内存耗尽错误,所以我想问一些方法,我怎样才能做得更好。
我在 DB2 数据库/数据表中有数据,如果有的话,我也可以接受服务器端解决方案。 任务基本上是我应该找到两个数据表之间的所有差异。我可以使用主键作为连接。
我还教导说,如果我将行连接成一个字符串并在主键连接上进行比较(在这种情况下,我只能有 2 列(,这可能是一个解决方案,但我应该得到两行之间的差异在哪里,所以这将是一个额外的步骤。
欢迎任何开箱即用的想法。
您可以尝试以下操作,就像使用方便的 DISTINCT 谓词(从 Db2 11.1 开始(一样。等效表达式可用于早期版本,但它们稍长一些。
WITH
A (ID, C1, C2) AS
(
VALUES
(1, '=', '=')
, (2, '=', '=')
, (4, 'A', '=')
, (5, '=', NULL)
, (6, 'A', 'A')
)
, B (ID, C1, C2) AS
(
VALUES
(1, '=', '=')
, (3, '=', '=')
, (4, 'B', '=')
, (5, '=', NULL)
, (6, 'B', 'B')
)
SELECT
COALESCE(A.ID, B.ID) AS ID
, CASE
WHEN A.ID IS NULL THEN '-A'
WHEN B.ID IS NULL THEN '-B'
ELSE ''
END
|| CASE WHEN A.ID = B.ID AND A.C1 IS DISTINCT FROM B.C1 THEN ', C1' ELSE '' END
|| CASE WHEN A.ID = B.ID AND A.C2 IS DISTINCT FROM B.C2 THEN ', C2' ELSE '' END
--...
--|| CASE WHEN A.ID = B.ID AND A.C60 IS DISTINCT FROM B.C60 THEN ', C60' ELSE '' END
AS FLAG
FROM A
FULL JOIN B ON B.ID = A.ID
WHERE
A.ID IS DISTINCT FROM A.ID
OR A.C1 IS DISTINCT FROM B.C1
OR A.C2 IS DISTINCT FROM B.C2
--...
--OR A.C60 IS DISTINCT FROM B.C60;
结果是:
|ID |FLAG |
|-----------|----------|
|4 |, C1 |
|6 |, C1, C2 |
|3 |-A |
|2 |-B |
我们在具有以下 OR 条件的 2 个表之间使用FULL OUTER JOIN
:
- 键 (
ID
( 仅对其中一个表为空(此键在对应表中没有匹配项( - 其中一个对应的列值存在差异
FLAG
列包含差异类型:
-TABNAME
- 表中缺少 KEYTABNAME
Cx
存在差异 - 对于每个这样的列
, Cx
- 列如果两个表中都有大量列,那么可以使用多个 Db2 系统视图为此SELECT
语句生成相应的表达式。
例如,如果我们想为SYSIBM.SYSTABLES
表生成这样的表达式, 使用其唯一索引之一(您必须选择这样的索引,最好是支持主键的索引(,然后按原样运行以下命令以检查:
SELECT
'|| CASE WHEN ' || I.KEY_EXPR || ' AND A.' || C.COLNAME || ' IS DISTINCT FROM B.' || C.COLNAME || ' THEN '', ' || COLNAME || ''' ELSE '''' END' AS SELECT_LIST_EXPR
, 'OR A.' || C.COLNAME || ' IS DISTINCT FROM B.' || C.COLNAME AS WHERE_EXPR
FROM
SYSCAT.COLUMNS C
, TABLE
(
SELECT LISTAGG('A.' || U.COLNAME || ' = B.' || U.COLNAME, ' AND ') AS KEY_EXPR
FROM SYSCAT.INDEXES I
JOIN SYSCAT.INDEXCOLUSE U ON U.INDSCHEMA = I.INDSCHEMA AND U.INDNAME = I.INDNAME
WHERE
I.TABSCHEMA=C.TABSCHEMA AND I.TABNAME=C.TABNAME
AND I.INDSCHEMA='SYSIBM' AND I.INDNAME='INDTABLES01'
AND I.UNIQUERULE IN ('P', 'U')
) I
WHERE C.TABSCHEMA='SYSIBM' AND C.TABNAME='SYSTABLES'
--FETCH FIRST 10 ROWS ONLY
;
一种(多种(方式是
(SELECT 'A', * FROM A EXCEPT ALL SELECT 'A', * FROM B)
UNION ALL
(SELECT 'B', * FROM B EXCEPT ALL SELECT 'B', * FROM A)
返回的第一列中有"A"的行在 TABLEA 中,但不在 TABLEB 中。
返回的第一列中有"B"的行在 TABLEB 中,但不在 TABLEA 中。