Сравнивая две таблицы с огромным количеством столбцов - PullRequest
4 голосов
/ 31 октября 2011

Я искал и не нашел решения, касающегося множества столбцов для сравнения.

У меня есть 1 большая таблица (ruleTable) с ок.300 столбцов, 1723 строки и другая таблица (sampleTable) с 1 строкой и точно такими же столбцами.Я хочу написать процедуру (с двумя аргументами: sampleTable и ruleTable), сравнивающую эту строку из второй таблицы с каждой строкой из первой таблицы.

Желаемый результат - таблица с 1723 строками и 3 столбцами: RULE_ID, WRONG (количество столбцов с одинаковым значением), RIGHT ((количество столбцов с разными значениями)

До настоящего времениЯ написал процедуру (вы можете увидеть ее ниже), но она определенно медленная, и для ее завершения требуются годы. У кого-нибудь есть идеи, как улучшить этот подход (или, возможно, полностью изменить) и справиться с этой проблемой?самая большая проблема заключается в количестве столбцов ...

PROCEDURE MAKE_CLASSIFICATION(sampleTable VARCHAR2, ruleTable VARCHAR2) AS
   l_query VARCHAR2(10000) := '';
   l_rulesColumns TEXTLIST := GetFeatureColumnList(ruleTable);
   l_rulesIDs TEXTLIST := GetTableColumnValues(ruleTable, 'ID');
   rule_value NUMBER;
   sample_value NUMBER;
   right NUMBER := 0;
   wrong NUMBER := 0;
BEGIN
   FOR j IN 1..l_rulesIDs.count()
   LOOP

      FOR i IN 1..l_rulesColumns.count()
      LOOP
         l_query := 'SELECT ' || l_rulesColumns(i) || ' FROM ' || ruleTable || ' WHERE ID=' || l_rulesIDs(j);
         EXECUTE IMMEDIATE l_query INTO rule_value;
         l_query := 'SELECT ' || l_rulesColumns(i) || ' FROM ' || sampleTable || ' WHERE rownum=1';
         EXECUTE IMMEDIATE l_query INTO sample_value;

         IF(rule_value = sample_value) THEN right:=right+1;
         ELSE wrong := wrong + 1;
         END IF;
      END LOOP;
      DBMS_output.put_line('right: ' || right || ';  wrong: ' || wrong );
      wrong := 0;
      right := 0;

   END LOOP;
END;

тип TEXTLIST определяется глобально:

 TYPE TEXTLIST IS VARRAY(1000000) OF VARCHAR2(10000);

GetFeatureColumnList -> эта функция возвращает TEXTLIST со списком имен таблиц colmun (без 'ID 'column)

GetTableColumnValues ​​-> эта функция возвращает TEXTLIST со списком всех значений COLUMN (в нашем случае - столбца' ID ')

Заранее благодарим за помощь друзей.

Ответы [ 2 ]

2 голосов
/ 31 октября 2011

Вы можете использовать метод 4 динамического SQL, чтобы позволить вам программно цикл по каждому столбцу

см .: http://www.oracle -developer.net / display.php? Id = 422

и Как перебирать столбцы в оракуле pl / sql курсор

или

как насчет динамического создания одного оператора, используя user_tab_cols затем скрестите таблицы и добавьте результаты сравнения каждого столбца

.... например

CREATE OR REPLACE PROCEDURE make_classification (sampletable VARCHAR2, ruletable VARCHAR2)
AS
   l_query          VARCHAR2 (10000) := '';
   right            NUMBER           := 0;
   wrong            NUMBER           := 0;
   l_number_of_columns NUMBER :=0;
   TYPE cur_typ IS REF CURSOR;
   c cur_typ;

BEGIN

    l_query:='SELECT ';
    FOR rec in (SELECT column_name FROM user_tab_cols  WHERE table_name=UPPER(ruleTable))
    LOOP
        IF l_number_of_columns > 0 THEN 
            l_query:=l_query||'+';
        END IF;    
        l_query:=l_query||'DECODE(t1.'||rec.column_name||',t2.'||rec.column_name||',1,0)';
        l_number_of_columns :=l_number_of_columns +1; 
    END LOOP;   

    l_query := l_query || ' AS cnt FROM '||ruletable||' t1,'|| sampletable || ' t2';

    --DBMS_OUTPUT.put_line (l_query);

    OPEN c FOR l_query;
    LOOP
        FETCH c INTO right;
        DBMS_OUTPUT.put_line ('right: ' || to_char(right) || ';  wrong: ' || to_char(l_number_of_columns-right));
        EXIT WHEN c%NOTFOUND;        
    END LOOP;
    CLOSE c;       
END;
1 голос
/ 31 октября 2011

Если вы используете 11g, я бы хотел использовать оператор UNPIVOT, чтобы превратить вашу таблицу с 300 столбцами в представление с 300 строками на каждую запись (всего 1723 * 300 строк). Затем используйте COUNT, чтобы определить количество правильных и неправильных ответов. тогда вы можете повернуть PIVOT назад, чтобы у вас был правильный и неправильный столбец.

Поскольку у вас так много столбцов, вы можете использовать программу PL / SQL для создания исходного запроса SQL, но я бы не использовал динамический SQL для его запуска каждый раз.

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