#mysql #sql #database-design
#mysql #sql #проектирование базы данных
Вопрос:
Я пытаюсь выяснить, каков наилучший способ вставить международную стандартную классификацию профессий в MySQL.
Вот подробная информация о категориях: http://www.ilo.org/wcmsp5/groups/public/—dgreports/—dcomm/—publ/documents/publication/wcms_172572.pdf
Также я нашел проект github: https://github.com/patriciomacadden/isco/blob/master/db/schema.rb Похоже, что он использует отдельные таблицы для разных уровней групп.
Мое текущее мнение состоит в том, чтобы создать единую таблицу и сохранить некоторые повторяющиеся данные, поскольку данные не будут часто меняться, а объем данных меньше тысячи строк. Например:
'l1','l2','l3','l4' are 'TINYINT' and 'level','name' are VARCHAR. So 'level' is the primary key
l1 |l2 |l3 |l4 |level|name
----|----|----|----|-----|--------
5 |null|null|null|5 |Services and Sales Workers
5 |1 |null|null|51 |Personal Services Workers
5 |1 |1 |null|511 |Travel Attendants, Conductors Guides
5 |1 |1 |1 |5111 |Travel Attendants and Travel Stewards
5 |1 |1 |2 |5112 |Transport Conductors
5 |1 |1 |3 |5113 |Travel Guides
Поле «уровень» — varchar, потому что мне может понадобиться получить все строки, включая верхнюю категорию.
ГДЕ уровень, ПОДОБНЫЙ «511%»
Я не уверен, что лучше иметь «уровень» как int, но, возможно, varchar имеет лучшие характеристики и при сортировке этих конкретных данных.
Я не уверен, нужны ли мне l1, l2, l3, l4 отдельно, но с таким небольшим количеством строк, возможно, не повредит некоторая избыточность.
Итак, вопрос в том, видите ли вы какие-либо очевидные ошибки в моем дизайне? Сможете ли вы улучшить это?
Я не уверен, нужно ли мне остерегаться дополнительных полей, потому что я еще не дочитал этот ISCO pdf…
Спасибо
Комментарии:
1. Это 433-страничный PDF-файл, возможно, объясните в абстрактных терминах, чего вы хотите. Тем не менее, значения L почти наверняка должны быть вертикальными, и было бы предпочтительнее избегать столбца «сводка», который дублирует данные, уже имеющиеся в строке (с неправильным типом данных).
2. Ну, я хочу импортировать ISCO в SQL наилучшим возможным способом. Достаточно ли это абстрактно? 🙂 Вы правы насчет L полей, и, вероятно, они мне вообще не нужны. Но я беспокоился, что могут быть случаи, о которых я не могу думать прямо сейчас, где они могут оказаться полезными.
Ответ №1:
Вам не нужны как l1 / l2 / l3 / l4, так и level: они полностью избыточны. Хранение одних и тех же данных двумя разными способами просто создает вероятность того, что где-то в процессе ошибка сделает их несовместимыми, и тогда вы получите странные результаты. Запрос, использующий l1/2/3/4 находит записи, отличные от запроса, использующего level, и пользователи недоумевают, почему их результаты не имеют смысла. Например, если на экране ввода данных используется level, и у вас есть код для разбиения его на l1/2/3/4 , пользователь запускает запрос, который под таблицей использует l1/2/3/4 и он находит ноль совпадающих записей. Затем он смотрит на экран, и запись прямо там! Или, что еще хуже, итоги не складываются и т. Д.
Трудно сказать, какой из двух отдать предпочтение. Большинство запросов, вероятно, проще писать с помощью одного поля: выберите бла-бла-бла, где level = ‘512’, или выберите бла-бла-бла, где level = ‘51%’, а затем выберите бла-бла-бла, где l1 = 5 и l2 = 1 и l3 = 2, а l4 равно нулю и т. Д. О, и тестирование более низких уровней без ссылки на более высокие уровни, вероятно, бессмысленно. То есть, когда бы вы когда-нибудь сказали выбрать бла-бла-бла, где l2 = 4, но не тестировать l1?
Уровень, безусловно, должен быть строкой, а не целым числом. Вы хотите, чтобы ’51’ сортировался до ‘512’, а не после. Вы бы никогда не стали делать арифметику над ними, верно? Что бы значило сказать chemist.level teacher.level или clerk.level * 3?
Ответ №2:
Я бы сделал
level VARCHAR(4) CHARACTER SET ascii
. (Взгляд на PDF, кажется, говорит, что 4 достаточно, но при необходимости увеличьте «4».)VARCHAR
будет сортировать «правильно»,INT
не будет.SUBSTR(level, 3, 1)
чтобы получить эквивалент l3, если вам нужно отобразить такой.- Вместо этого
SUBSTR
вы получите пустую строкуNULL
; вы можете использоватьIF(,)
илиCASE...
отображать ее любым удобным для вас способом.