Дизайн базы данных и запрос исторических табличных данных - PullRequest
0 голосов
/ 18 мая 2018

У меня есть набор таблиц HTML, в которых со временем хранятся вопросы и ответы на вопросы.Каждый вопрос имеет свою собственную таблицу HTML, столбцы - это годы, строки - это ответы, затем в отдельных ячейках указывается количество ответов за этот год, как показано ниже:

enter image description here

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

Сейчас у меня есть следующий дизайн таблицы:

question

id int(11) unsigned AI PK
name varchar(255) UNQ
number varchar(255) UNQ
text

год

id int(11) unsigned AI PK
question_id int(11) unsigned FK
name varchar(255) UNQ (question_id + name)

ответ

id int(11) unsigned AI PK
question_id int(11) unsigned FK
name varchar(255) UNQ (question_id + name)

data

id int(11) unsigned AI PK
question_id int(11) unsigned FK
year_id int(11) unsigned FK
response_id int(11) unsigned FK UNQ (year_id + response_id)
count int(11) unsigned NULL

Любая помощь или улучшения будут с благодарностью.

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

В общем, если у вас есть ключ UNIQUE (это то, что означает «UNQ» ??), используйте if для PRIMARY KEY.

«имен» обычно не нужноVARCHAR(255).Выберите меньший размер.

"числа" обычно не должны быть VARCHAR(255).Выберите более подходящий тип данных.

Напишите схему в синтаксисе CREATE TABLE;У меня возникли серьезные проблемы при разборе вашего описания запуска.

Что означает «0,00»?Это выводится из других данных?Если это так, не храните его.

По вторым изображениям, я думаю, у вас есть 1 таблица:

CREATE TABLE foo (
    year YEAR NULL,
    gender ENUM('male', 'female') NOT NULL,
    val SMALLINT UNSIGNED NOT NULL,
    PRIMARY KEY(year, gender)
) ENGINE=InnoDB;

Я не понимаю значения слова «1959-1974»., но это может быть

    cohort VARHAR(20) NOT NULL

и замена gender во второй таблице, которая в противном случае выглядит как приведенная выше таблица.

Но ... Вы действительно не можете разработать схему безпонимание того, что будет сделано с данными.Есть ли у вас предварительные SELECTs?

0 голосов
/ 29 мая 2018

уже есть хорошие идеи для структурированной версии вашей целевой модели данных - если вы хотите, чтобы структура вашей статистики была немного более гибкой, но при этом вы могли со временем разбивать и группировать, то альтернативой может быть следованиеШаблон / dw для моделирования ваших данных

следующие «логические» и будут коррелировать с атрибутами / измерениями в таблице фактов согласно kimball et.al. , где 'зерном' таблицы фактов является 'src html file + table + row + cell + value (s)', при условии, что ваши значения согласованы во времени

  • (я заметил на вашем изображении, что есть пара таблиц для одного HTML-файла и несколько значений в каждой ячейке)

  • group_srcfile (указывает на местоположение висходный html-файл / таблица / строка / ячейка, и, возможно, вы также можете сохранить исходный html-файл на случай, если позже потребуется выполнить вскрытие)

  • group_cohort (указывает нанормализованная когорта, например, «18-24 лет в возрасте» или «мужчины в течение времени»)

  • group_question (указывает на определение вопроса - это все те же вопросы со временем)

  • question_id (определение вопроса + год вопроса)

  • question_year (это год, когда был задан вопрос)

  • cohort_start_year (это год, в котором когорте задавался вопрос)

  • cohort_end_year (это конецгодКогорту задавали вопрос)

  • cohort_start_age (если применимо, будет нормализовано 'xxxx - yyyy', например: '18')

  • cohort_end_age (это либо указано, либо выведено как «xxxx - present», где «present» - это год файла отчета html)

  • значения 1.. n должны считать одни и те же вещи, в противном случае вам нужно будет их также разделить

, чтобы получить достойный результат, вам нужно будет завершить вопросы по вашим даннымтаблицу, но что бы вы ни делали, было бы относительно просто экспортировать html с использованием php

. Я подумал о методе загрузки данных в mysql, но без твердых примеров html-файлов, являющихся источникомваши данные, трудно написать конкретный код (т.е.откройте в вашем браузере и «просмотреть исходный код» или эквивалентный)

в качестве общего подхода, я бы проанализировал каждый факт (ячейка таблицы td) из html, используя php и DOMDocument, а затем выдал строку вденормализованная форма для последующей загрузки в промежуточную таблицу и, в конечном счете, в вашу таблицу фактов

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

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

(я бы, вероятно, использовал интеграция данных pentaho для обработки второгофаза - потоковый анализатор XML не может обработать первый: слишком строго)


я нашел этот тест html file , который был достаточно стар, чтобы заставить меня пойти и выпить свой последний кофе при одной мысли о бесконечной переписывании кода очистки, чтобы учесть бесконечные изменения макета, любезно предоставленные «dreamtheaver» ...

Как только мои руки достаточно стабилизировались, и кровоток вернулся к нормальному состоянию, я направил машинный дух и произвел следующий php - заметно отсутствует какой-либо вид реструктуризации / денормализации исходной таблицы:

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$dom = new DOMDocument();

$srcfile = 'testxmlparser.html';
$dom->loadHTMLFile( $srcfile, NULL );

echo 'odom is: ' . ($dom ? 'nice':'naughty') . PHP_EOL;

if( $dom ) {
  // get all the table rows in the document
  $tblrows = $dom->getElementsByTagName('tr');

  foreach( $tblrows as $trrow ) {
    $tblcells = $trrow->getElementsByTagName('td');
    $incr = 0;

    // buffer this table row's cell (td) data that we encounter, in case it is interesting...
    $srowbuf = '';
    foreach( $tblcells as $tdcell ) {
      $srowbuf = ($srowbuf . $tdcell->nodeValue);
      if( 1 <= $incr++ )
        $srowbuf = ($srowbuf . '+|');
    }
    // we know the table data we're interested in has 12 cells only
    if( 12 == $incr )
      echo $srowbuf . '+|' . $incr . '+|' . $srcfile . PHP_EOL;
  }
}

?>
0 голосов
/ 23 мая 2018

Вам не нужна таблица year, поскольку год является вопросом - независимо.

И изменить таблицу data

  • year_id int(11) unsigned FK до year SMALLINT(4) UNSIGNED

  • UNQ (year_id + response_id) до UNQ (year + response_id)

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