Как бы вы сравнили две большие (приблизительно 2 мил строки х 60 столбцы) таблицы данных? - PullRequest
1 голос
/ 29 января 2020

Я видел несколько методов, которые, как я могу сравнить (сравнение_df, dplyr, и т. Д. c.), И они достаточно эффективны. Однако, когда я хотел бы сравнить большие или большие кадры данных, я получаю сообщение об ошибке исчерпания памяти, поэтому я хотел бы спросить некоторый метод, как я могу сделать это лучше.

У меня есть данные в базах данных / таблицах данных DB2, я мог бы принимать решения на стороне сервера, если таковые имеются. Основная задача состоит в том, чтобы найти все различия между двумя таблицами данных. Я мог бы использовать первичный ключ в качестве соединения.

Также я учил, что это могло бы быть решением, если бы я объединял строки в одну строку и сравнивал это при соединении с первичным ключом (и в этом случае у меня могло быть только 2 столбца), но я должен получить, где есть разница между двумя строками, так что это будет лишним шагом.

Любые нестандартные идеи приветствуются.

Ответы [ 2 ]

0 голосов
/ 31 января 2020

Вы можете попробовать следующее как есть , используя удобный 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        |

Мы используем FULL OUTER JOIN между двумя таблицами со следующими ИЛИ условия:

  • КЛЮЧ (ID) равен ПУСТО (NULL) только для одной из этих таблиц (в этой таблице нет совпадений по этому КЛЮЧУ)
  • Существует разница в одном из соответствующих значений столбца

В столбце FLAG указан тип разницы:

  • -TABNAME - отсутствие ключа в таблице TABNAME
  • , Cx - существует разница в столбце Cx - для каждого такого столбца

Если в обеих таблицах имеется большое количество столбцов, вы можете сгенерируйте соответствующие выражения для этого оператора SELECT, используя несколько системных представлений Db2.
Например, если мы хотим сгенерировать такие выражения для таблицы SYSIBM.SYSTABLES, используя один из ее уникальных индексов (вы должны выбрать такой Индекс, предпочтительно одна поддержка ng первичный ключ), затем запустите его как есть, чтобы проверить:

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
;
0 голосов
/ 30 января 2020

Один из способов (из многих) -

(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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...