Значения Varchar для числовой классификации - PullRequest
3 голосов
/ 01 июля 2011

У меня есть база данных, содержащая три таблицы:

  1. практики - 8 полей
  2. пациентов - 47 полей
  3. обострений - 11 полей

Большинство полей в этих таблицах записаны в формате varchar, другие поля включают целые числа, числа с двойными числами и даты.

Мне нужно преобразовать эти данные в численно классифицированные данные , чтобы статистик мог использовать их для экстраполяции любых закономерностей в данных. Чтобы добиться этого, мне нужно будет преобразовать поля varchar в целые числа, которые представляют классификацию, к которой относится строка, например, «Серьезность», которая имеет следующие возможные строковые значения:

  1. Мягкий
  2. Умеренное
  3. Тяжелый
  4. Очень тяжелый

Это поле в таблице пациентов имеет конечный список строковых значений, которые могут появляться, другие поля имеют бесконечную возможность строковых значений, которые не могут быть классифицированы, пока они не обнаружены в моей базе данных (если я не реализую некоторую форму интеллектуального подхода) .

В настоящее время я просто пытаюсь построить лучший подход к преобразованию каждого поля для всех записей в каждой из 3 таблиц в числовые значения. Пока псевдокод, который у меня в голове, выглядит следующим образом (он не полный):

 function profileDatabase 
   for each table in database 
     for each field that is of type varchar
       select all distinct values and insert into classfication table for that field
     end for
   end for

 function classifyDatabase
   for each table in database 
     for each field that is of type varchar
       // do something efficient to build an insert string to place into new table
     end for
   end for

Может ли кто-нибудь предложить наилучший способ выполнения этого процесса, чтобы он был эффективным, учитывая, что в настоящее время в системе насчитывается более 100 практик, 15 000 пациентов и 55 000 обострений. Мне не нужно реализовывать это в PHP, сборка, я бы предпочел сделать это. Любые указатели относительно того, как структурировать это, было бы замечательно, так как я не уверен, что мой подход - лучший подход.

Этот процесс должен будет выполняться каждый месяц в течение следующих двух лет, поскольку база данных увеличивается до 100 000 пациентов.

Ответы [ 2 ]

0 голосов
/ 06 июля 2011

Мне удалось построить собственное решение этой проблемы, которое работает в разумные сроки.Для тех, кто заинтересован, или для тех, кто может столкнуться с подобной проблемой, здесь я использовал подход:

PHP-скрипт, который запускается как задание cron путем вызова php scriptName.php [database-name].Сценарий создает классифицированную таблицу для каждого имени таблицы в базе данных (которая не является таблицей поиска для этого процесса).Настройка каждой классификации создает новую таблицу, которая имитирует формат базовой таблицы, но устанавливает все поля, чтобы разрешить значения NULL.Затем он создает пустые строки для каждой из строк, найденных в базовой таблице.Затем процесс продолжается, анализируя каждое поле таблицы по полю и обновляя каждую строку правильным классом для этого поля.

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

Код сценария:

include ("../application.php");

profileDatabase("coco");
classifyDatabase("coco");

function profileDatabase($database) {
    mysql_select_db($database);
    $query = "SHOW TABLES";
    $result = db_query($query);
    $dbProfile = array();
    while ($obj = mysql_fetch_array($result)) {
        if (!preg_match("/_/", $obj[0])) {
            $dbProfile[$obj[0]] = profileTable($obj[0]);
        }
    }
    return $dbProfile;
}

function profileTable($table) {
    $tblProfile = array();
    $query = "DESCRIBE $table";
    $result = db_query($query);
    while ($obj = mysql_fetch_array($result)) {
        $type = substr($obj[1], 0, 7);
//echo $type;
        if (preg_match("/varchar/", $obj[1]) && (!preg_match("/Id/", $obj[0]) && !preg_match("/date/", $obj[0]) && !preg_match("/dob/", $obj[0]))) {
            $x = createLookup($obj[0], $table);
            $arr = array($obj[0], $x);
            $tblProfile[] = $arr;
        }
    }
    return $tblProfile;
}

function getDistinctValues($field, $table) {
    $distinct = array();
    $query = "SELECT DISTINCT $field as 'value', COUNT($field) as 'no' FROM $table GROUP BY $field ORDER BY no DESC";
    $result = db_query($query);
    while ($obj = mysql_fetch_array($result)) {
        $distinct[] = $obj;
    }
    return $distinct;
}

function createLookup($field, $table) {
    $query = "CREATE TABLE IF NOT EXISTS `" . $table . "_" . $field . "`
(
`id` int(5) NOT NULL auto_increment,
`value` varchar(255) NOT NULL,
`no` int(5) NOT NULL,
`map1` int(3) NOT NULL,
`map2` int(3) NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1";
    db_query($query);
    $distinct = getDistinctValues($field, $table);
    $count = count($distinct);
    foreach ($distinct as $val) {
        $val['value'] = addslashes($val['value']);
        $rs = db_query("SELECT id FROM " . $table . "_" . $field . " WHERE value = '" . $val['value'] . "' LIMIT 1");
        if (mysql_num_rows($rs) == 0) {
            $sql = "INSERT INTO " . $table . "_" . $field . " (value,no) VALUES ('" . $val['value'] . "', " . $val['no'] . ")";
        } else {
            $sql = "UPDATE " . $table . "_" . $field . " (value,no) VALUES ('" . $val['value'] . "', " . $val['no'] . ")";
        }
        db_query($sql);
    }
    return $count;
}

function classifyDatabase($database) {
    mysql_select_db($database);
    $query = "SHOW TABLES";
    $result = db_query($query);
    $dbProfile = array();
    while ($obj = mysql_fetch_array($result)) {
        if (!preg_match("/_/", $obj[0])) {
            classifyTable($obj[0]);
            //echo "Classfied $obj[0]\n";
        }
    }
}

function classifyTable($table) {
    $query = "SHOW TABLES";
    $result = db_query($query);
    $dbProfile = array();
    $setup = true;
    while ($obj = mysql_fetch_array($result)) {
        if ($obj[0] == "classify_" . $table)
            $setup = false;
    }
    if ($setup) {
        setupClassifyTable($table);
        //echo "Setup $table\n";
    }

    $query = "DESCRIBE $table";
    $result = db_query($query);
    while ($obj = mysql_fetch_array($result)) {
        if (preg_match("/varchar/", $obj[1]) && (!preg_match("/Id/", $obj[0]) && !preg_match("/date/", $obj[0]) && !preg_match("/dob/", $obj[0]))) {
            $rs = db_query("
        SELECT t.entryId, t.$obj[0], COALESCE(tc.map1,99) as 'group' FROM $table t 
        LEFT JOIN " . $table . "_$obj[0] tc ON t.$obj[0] = tc.value 
        ORDER BY tc.map1 ASC");
            while ($obj2 = mysql_fetch_object($rs)) {
                $sql = "UPDATE classify_$table SET $obj[0] = $obj2->group WHERE entryId = $obj2->entryId";
                db_query($sql);
            }
        } else {
            if ($obj[0] != "entryId") {
                $rs = db_query("
        SELECT t.entryId, t.$obj[0] as 'value' FROM $table t");
                while ($obj2 = mysql_fetch_object($rs)) {
                    $sql = "UPDATE classify_$table SET $obj[0] = '" . addslashes($obj2->value) . "' WHERE entryId = $obj2->entryId";
                    db_query($sql);
                }
            }
        }
    }
}

function setupClassifyTable($table) {
    $tblProfile = array();
    $query = "DESCRIBE $table";
    $result = db_query($query);
    $create = "CREATE TABLE IF NOT EXISTS `classify_$table` (";
    while ($obj = mysql_fetch_array($result)) {
        if (preg_match("/varchar/", $obj[1]) && (!preg_match("/Id/", $obj[0]) && !preg_match("/date/", $obj[0]) && !preg_match("/dob/", $obj[0]))) {
            //echo $obj[1]. " matches<br/>";
            $create .= "$obj[0] int(3) NULL,";
        } else {
            $create .= "$obj[0] $obj[1] NULL,";
        }
    }
    $create .= "PRIMARY KEY(`entryId`)) ENGINE=MyISAM DEFAULT CHARSET=latin1";
    db_query($create);
    $result = mysql_query("SELECT entryId FROM $table");
    while ($obj = mysql_fetch_object($result)) {
        db_query("INSERT IGNORE INTO classify_$table (entryId) VALUES ($obj->entryId)");
    }
}

?>
0 голосов
/ 01 июля 2011

Может быть http://dev.mysql.com/doc/refman/5.1/en/procedure-analyse.html поможет получить общее представление о том, как используются поля.

...