Найкращий спосіб зберігання одиниць у базі даних


21

Я успадкував велику (SQLServer) базу даних із сотнями стовпців, які представляють суми тієї чи іншої речі. Одиниці для цих значень (наприклад, "галони", "дюйми" тощо) зберігаються в полі MS_Description розширених властивостей. Мені цікаво, чи є кращий спосіб зберігати цю інформацію. Я припускаю, що це добре для цілей документації, але було б важко зробити надійні розрахунки конверсій одиниць на основі цих даних. На даний момент я не готовий внести інвазивні зміни, але якщо я отримаю можливість це зробити, що є рекомендованою найкращою практикою в цьому плані? Опції, вгорі голови, можуть включати:

  • Змініть назву стовпця на включені одиниці (наприклад, "TotalVolumeInGallons". Це зробить інформацію трохи доступнішою, але вона все ще здається слабкою.)
  • Додайте окремий стовпець "Одиниці", щоб відповідати кожному стовпцю "Сума" (цей стовпець може бути nvarchar АБО це може бути зовнішнім ключем до окремої таблиці Units, що може полегшити підрахунок конверсій одиниць. З іншого боку, додавши так багато стовпців могли досить подвоїти розмір моєї бази даних - із жахливо зайвими даними.)
  • Створіть нове поле в Розширених властивостях, призначене спеціально для одиниць. (На жаль, я не думаю, що це може бути зовнішнім ключем до таблиці Units.)
  • Чи є інша ідея, яку я оглядаю?

ОНОВЛЕННЯ: Після прочитання відповіді @Todd Everett у мене виникло можливе рішення, тому я збираюся йти вперед і відповісти на власне питання. (Дивись нижче)


Найкраща практика полягає в тому, щоб єдина система вимірювань використовувалася універсально та послідовно впродовж усього застосування. SI - це система вибору. Значення в інших системах будуть перетворені під час завантаження або в презентаційний шар, де кожен користувач може вибрати свій бажаний набір.
Майкл Грін

Відповіді:


12

Оскільки ви згадуєте сотні колонок, я б розглядав дизайн EAV . Хоча Джо Селко застерігає від цього , я думаю, що це може бути застосовано у вашому випадку використання. Здається, що всі ваші "суми" - це цифри, тому ви б уникнули проблем із кастингом, які Джо описує, та необхідності робити кожне "значення" рядком. Він буде працювати ще краще, якщо всі суми будуть цілими числами, але можуть працювати також, якщо деякі є десятковими. З огляду на одиниці вимірювання, ви можете піти на крок далі та реалізувати модель стилю "універсальної моделі даних", засновану на цій статті Девіда Хея, а також окреслену у своїй книзі " Шаблони моделі даних: конвенції думки". Ця модель має додаткову перевагу в налаштуванні, які "суми" застосовуються до яких "речей", якщо вам це потрібно. Ще одним кроком, показаним у книзі на сторінці 162, є таблиця перетворення одиниці виміру, яку можна використовувати для перетворення між різними одиницями вимірювання. Ось приклад:

UOM Conversion              

UOM From    UOM To        Cal Step  Operator Factor Constant
Kilograms   Pounds        1         *        2.2
Celsius     Fahrenheit    1         *        1.8
Celsius     Fahrenheit    2         +               32

Це говорить про те, що для перетворення з Kg в Lb перший крок - це множення Kg на 2,2. Існує також константа, якщо конверсія також повинна включати постійне значення та можливість створення декількох кроків. Отже, перетворюючи скажімо Цельсій у Фаренгейт, ви помножите Цельсій на 1,8, а потім додасте 32. Ключем буде від UOM, до UOM та Крок розрахунку.

Це коштує мої 2 копійки. Я сподіваюся, що ці посилання дають вам добру їжу для роздумів, якщо ви коли-небудь отримаєте можливість зробити перезавантаження на поточному дизайні.


Дякую за дуже цікаву їжу для роздумів - я багато чого навчився. Однак я не думаю, що EAV є відповідною моделлю в моєму випадку (якщо я правильно розумію вашу пропозицію), тому що, хоча у нас є стотиці стовпців, вони аж ніяк не рідкі. Однак цей DID викликає споріднену ідею (див. ОНОВЛЕННЯ в моїй оригінальній публікації).
kmote

Ваша ідея для мене звучить досить добре - я не можу придумати жодних питань, пов'язаних з нею, крім тих, що ви вже вказали. Але якщо стовпці можна перейменувати / змінити, це буде проблемою в будь-якому дизайні. Це коли співпраця - це весело - ідея, з якої ніхто з нас не думав починати!
Тодд Еверетт

8

Вся робота.

Зауважте, що у другому випадку ви не можете додавати яблука та апельсини, тому дані надзвичайно легко піддаються неправильному тлумаченню.

Також зауважте, що конверсії не можуть бути дуже безпечними і сприйнятливі до помилок округлення, переповнення тощо.

Крім того, існують такі фізичні проблеми, як питома вага та температура. Перетворення 20 галонів води в фунти вимагає від вас знання густини води. Але щільність води змінюється в міру зміни температури, тому вам може знадобитися або знати щільність, яка є одночасно з вимірюванням, або температуру аналогічно, і використовувати коефіцієнт корекції об'єму.

У разі розширених властивостей це корисно лише для документації - хороша назва стовпця краще для документації. Проблема зі стовпцем, що має на увазі назви у фіксованій одиниці, полягає в тому, що ви поміняєте себе в кут при зміні одиниць вимірювання - новий клієнт хоче масла в бочках, а не в галонах - і це було б добре, оскільки їх дані власна база даних, але назва стовпця зараз вводить в оману.

Інший варіант - зберігати канонічні версії у фіксованих одиницях (тобто завжди кілограми та метри) на додаток до різних оригінальних вимірювань. Операції сукупності на фіксованих одиницях повинні бути прекрасними (за винятком випадків, якщо ви не додавали температури), але ви не втрачаєте початкового вимірювання.


1
Потенційне «неправильне тлумачення», яке ви згадуєте, - це саме одна з проблем, які я маю щодо поточної архітектури цієї бази даних, - і те, що я намагаюся знайти спосіб зменшити.
kmote

1
чудовий момент щодо потенційного недоліку рішення імені стовпця.
kmote

1
@kmote Це не проста проблема - у нас є звіти, де окремі транзакції можуть мати різні оригінальні одиниці вимірювання, але також є загальна сума - яка є загальною після перетворення на обрану користувачем одиницю.
Кейд Ру

7

Просте рішення, яке добре працювало для мене в минулому, - зберігати всі ваші дані у «базових» одиницях. Наприклад, ваша базова одиниця для довжини може бути міліметрів, а ваша базова одиниця для ваги може бути кілограмами. Це рішення може спричинити необхідність перетворення деяких існуючих даних у базовий блок, якщо цього ще немає.

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

Таблиці перетворення одиниць для перетворення між різними підтримуваними одиницями можуть бути жорстко кодовані у вашій програмі, оскільки нові одиниці вимірювання змінюються вкрай рідко.

Зверніть увагу, що пов'язане з іншою проблемою полягає в тому, що під час зберігання часових позначок у базі даних завжди потрібно зберігати їх у "базовому" блоці - UTC .

Ще одна відповідна відповідь на цю тему ...


5

Оскільки будь-яка одиниця може бути перетворена в іншу одиницю одного типу з формулою:

y = ((x + xOffset) * multiplicand / denominator) + yOffset

Я б створив таблицю, яка містить типи одиниць плюс ці 4 значення.

From Unit     To Unit      Unit Type    From Offset    Multiplicand    Denominator    To Offset
'milligrams'  'grams'      'mass'       0              1               1000           0
'grams'      'kilograms'   'mass'       0              1               1000           0
'grams'      'ounces'      'mass'       0              100000          2835           0
'ounces'     'pound'       'mass'       0              1               16             0

Після того, як ви додали всі вимірювання, які ви, ймовірно, перетворите на та з обох сторін списку, запустіть Запит, куди ви вставляєте зворотну операцію, просто відкинувши зсуви та замінивши мультиплікацію та знаменник, а також на одиницю і на одиницю.

Щоб додати перетворення між усіма типами, перехресне з'єднання З деякими фільтрами можна вставити залишки конверсій.


3

Прочитавши відповідь @Todd Everett, у мене виникло рішення, тому я збираюся йти вперед і відповісти на власне запитання. Те , що я думаю , що я збираюся зробити , це створити окрему ColumnUnitsтаблицю з чотирма стовпцями: Schema, Table, Column, UnitsID(де UnitsID є FK в окрему UnitsOfMeasureтаблицю), таким чином , відображення будь-якого заданого стовпчика в пов'язаної з ним одиниці виміру. Очевидно, найбільшим недоліком цієї ідеї є те, що розробникам доведеться пам’ятати, щоб редагувати цю таблицю щоразу, коли вони перейменовують стовпчик або таблицю [ можливо, використовувати тригер DDL ? ], інакше система зламається. Але якщо припустити, що такі перейменування зустрічаються рідко, і цех невеликого розміру (у моєму випадку лише одна людина) ця архітектура повинна бути працездатною. Перевага полягає в тому, що жодних інвазивних змін у поточну БД не потрібно вносити, і мені потрібно зберігати значення лише один раз для кожного стовпця, а не один раз у рядку, як цього вимагає мій другий варіант у моєму початковому дописі.


цікава головоломка ... і цікава ідея у вас є. Ваша ідея полегшила б запит, але, здається, не дуже досягла. Ви щойно перенесли довідкові дані в інше місце. що мене найбільше турбує у цьому дизайні
Сер присягає,

... це те, що якщо елемент має більше атрибутів, вам все одно потрібно додати більше стовпців. тому мені подобається пропозиція @todd everett щодо ева-дизайну.
Сер клянеться-лот
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.