Нормализация таблицы: поиск уникальных столбцов по ряду строк (Oracle 10.x) - PullRequest
3 голосов
/ 29 сентября 2010

У меня есть таблица со следующей структурой:

WorkerPersons
-------------------------------
ID          (PK)
PersonID    (Indicates which version of Person the record describes)
SomeColumn1 (data specific to Worker)
SomeColumn2 (data specific to Person)
....
SomeColumnN
-------------------------------

Как вы можете видеть, это денормализованная таблица, в которой хранятся данные как Worker, так и Person (и многие версии одного Person) в одной таблице. Мое желание состоит в том, чтобы нормализовать эту таблицу, однако, поскольку таблица содержит много данных (много много столбцов), я должен быть уверен, какие столбцы должны идти в таблицу Workers, а какие - в таблицу Persons. Результат должен быть таким:

Workers                 Persons
----------------------- ---------------------
ID                      ID
PersonID (now a FK)     PersonColumn1
WorkerColumn1           PersonColumn2
WorkerColumn2           ...
...                     PersonColumnN
WorkerColumnN
----------------------- ---------------------

Для этого мне нужно проанализировать, какие данные различаются по объему Person по всем уникальным Person (которые отделены PersonID в WorkerPersons). Например:

WorkerPersons
-------------------------------------------------------
ID      PersonID      Column1      Column2      Column3
-------------------------------------------------------
1       PersonA       10.1         John Doe     Single
2       PersonA       10.1         John Doe     Single
3       PersonA       10.1         John Doe     Married
4       PersonB       09.2         Sully        Single
5       PersonB       09.2         Sullivan     Single

В этом случае имеется 3 версии PersonA и 2 версии PersonB. Значения Column1 всегда одинаковы для всех версий Person, и мы можем переместить этот столбец в таблицу Worker. Но значения столбца 2 и столбца 3 изменяются в разных версиях Person, поэтому эти значения следует переместить в таблицу Person.

Не представляю, у меня около 10 таких таблиц, которые нужно нормализовать, с примерно 40 столбцами в каждой. Каждый стол вмещает от 500 до 5 метров.

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

Пожалуйста, сообщите.

С наилучшими пожеланиями, Андрей

Ответы [ 2 ]

3 голосов
/ 29 сентября 2010

Так как 10 таблиц не много, вот (своего рода) псевдокод

for each table_name in tables
  for each column_name in columns
    case (exists (select 1
          from table_name
          group by PersonID
          having min(column_name) = max(column_name))
       when true then 'Worker'
       when false then 'Person'
    end case
  end for
end for

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

РЕДАКТИРОВАТЬ: Приведенное выше предполагает не NULL с в column_name.

EDIT2: Другие варианты основного запроса могут быть

SELECT 1
FROM 
(SELECT COUNT(DISTINCT column_name) AS distinct_values_by_pid
FROM table_name
GROUP BY PersonID) T
HAVING MIN(distinct_values_by_pid) = MAX(distinct_values_by_pid)

, который будет возвращать строку, если все значения для PersonID одинаковы.(этот запрос также имеет проблемы с NULLS, но я рассматриваю NULL как отдельную проблему; вы всегда можете привести NULL к некоторому значению вне домена для целей вышеупомянутого запроса)

Вышеупомянутый запрос может такжезаписывается как

SELECT MIN(c1)=MAX(c1), MIN(c2)=MAX(c2), ...
FROM 
(SELECT COUNT(DISTINCT column_name_1) AS c1, COUNT(DISTINCT column_name_2) AS c2, ...
FROM table_name
GROUP BY PersonID) T

, который будет проверять несколько столбцов одновременно, возвращая true для столбцов, принадлежащих «Workers», и false для столбцов, которые должны входить в «Persons».

1 голос
/ 02 октября 2010

Спасибо, но я решил эту проблему, позволив Excel создать серию выборок по информации о схеме таблицы.Последний запрос, который он сгенерировал, был длинным списком выбора, но он работал (хотя он выполнялся более часа).«Основной запрос» (фактически формула в Excel для создания основного запроса):

=IF(AND(C17<>"CLOB";C17<>"NCLOB");"SELECT '"&A17&".'||initcap('"&B17&"') description,
decode(count(*),0,'SAME OVE VERSIONS','DIFFERENT OVER VERSIONS') values FROM (SELECT 
objektid, count(DISTINCT nvl("&B17&","&IF(C17="DATE";"'01.02.0004'";IF(C17="VARCHAR2"
;"'!#¤¤%¤(%#¤%AS'";"-1234561"))&")) OVER (PARTITION BY objectid) arv FROM "&A17&") 
WHERE number > 1 union all";"SELECT '"&A17&".'||initcap('"&B17&"') description, 'CLOB
field' values from dual union all")
...