Я работаю с данными, которыми исходно снабжают как рациональные числа. У меня есть гладкий универсальный класс C#, который красиво представляет эти данные в C# и позволяет преобразование во многие другие формы. К сожалению, когда я оборачиваюсь и хочу сохранить это в SQL, у меня есть пара решений в памяти, но ни один из них не очень удовлетворяет.
Вот пример. У меня есть необработанное значение 2/3
который мой new Rational
легко дескрипторы в C#. Опции, о которых я думал для хранения этого в базе данных, следующие:
Так же, как десятичное число/плавающая точка, т.е. значение = 0.66666667
из различной точности и точности. Профессионалы: это позволяет мне запрашивать данные, например, находить значения <1. Недостатки: это имеет потерю точности, и это ужасно, когда я иду для отображения этого простого значения назад в UI.
Хранилище как два точных целочисленных поля, например, числитель = 2
, знаменатель = 3
из различной точности и точности. Профессионалы: Это позволяет мне точно представить исходное значение и отобразить его в его самой простой форме позже. Недостатки: у Меня теперь есть два поля для представления этого значения, и запросы теперь сложный/меньшее количество эффективные, поскольку каждый запрос должен выполнить арифметику, например, найти числитель / знаменатель <1.
Сериализируйте как строковые данные, т.е. "2/3"
. Я смог бы знать макс. длину строки и иметь varchar, который мог содержать это. Профессионалы: я вернулся к одному полю, но с точным представлением. Недостатки: запросы в значительной степени арестованы, и оплатите стоимость сериализации.
Комбинация № 1 и № 2. Профессионалы: легко/эффективно запрос для диапазонов значений, и имеет точные значения в UI. Недостатки: три поля (!?!) для содержания одной части данных, должен сохранить несколько представлений в синхронизации, которая повреждает D.R.Y.
Комбинация № 1 и № 3. Профессионалы: легко/эффективно запрос для диапазонов значений, и имеет точные значения в UI. Недостатки: отступите к двум полям для содержания данных части, должен сохранить несколько представлений в синхронизации, которая повреждает D.R.Y., и должен оплатить дополнительные издержки сериализации.
У кого-либо есть другое out-of-the-box решение, которое лучше, чем они? Есть ли другие вещи, которые я не рассматриваю? Существует ли относительно простой способ сделать это в SQL, о котором я просто не знаю?
Я бы, вероятно, выбрал вариант №4, но использовал вычисляемый столбец для третьего столбца, чтобы избежать проблем с синхронизацией / СУХОЙ (а также означает, что на самом деле вы храните только 2 столбца, избегая "трех" поля "проблема).
В SQL-сервере вычисляемый столбец определяется следующим образом:
CREATE TABLE dbo.Whatever(
Numerator INT NOT NULL,
Denominator INT NOT NULL,
Value AS (Numerator / Denominator) PERSISTED
)
(обратите внимание, что вам может потребоваться преобразование типов и проверка того, что знаменатель не равен нулю и т. д.).
Кроме того, SQL 2005 добавлен вычисляемый столбец PERSISTED, который избавлялся от вычислений во время запроса.
Если вы используете SQL Server 2005 или 2008, у вас есть возможность определить свои собственные типы данных CLR :
Начиная с SQL Server 2005, вы может использовать определяемые пользователем типы (UDT) для расширить систему скалярных типов сервер, позволяющий хранить CLR объекты в базе данных SQL Server. UDT может содержать несколько элементов и может иметь поведение, различая его из традиционных типов данных псевдонимов которые состоят из одного SQL Server системный тип данных.
Поскольку доступ к UDT осуществляется систему в целом, их использование для сложные типы данных могут отрицательно влияние на производительность. Сложные данные обычно лучше всего моделируется с использованием традиционные строки и таблицы. UDT в SQL Server хорошо подходит для следующее:
- Дата, время, валюта и расширенные числовые типы
- Геопространственные приложения
- Закодированные или зашифрованные данные
Если вы можете жить с ограничениями, я не могу представить лучшего способа данные карты, которые вы уже записываете в специальном классе.
Язык, C # или другой, округляет 2/3 в заданной позиции точности. Если для того, над чем вы работаете, допустимо использовать десятичные значения, скажем, в научном представлении 10, тогда установите точность в db.
Если точность действительно вызывает беспокойство, тогда разделите числитель и знаменатель. Это гарантирует, что у вас всегда будет доступ к любой точности, которую вы хотите, и вы можете использовать вычисляемый столбец для представления значения для быстрой фильтрации:
numerator INT,
denominator INT,
result AS CASE WHEN denominator > 0 THEN numerator / denominator ELSE NULL END
Я немного поэкспериментировал с использованием геометрического типа данных в SQL Server 2008 для хранения рациональных чисел и управления ими. По сути, я предполагаю, что числитель помещается в слот X, а знаменатель - в слот Y фиктивной геометрической точки.
Это было хорошо для моих нужд, но могло быть бесполезно для ваших. Это будет зависеть от ваших приоритетов (производительность, читаемость кода и т. Д.). Я лично обнаружил, что T-SQL для обработки геометрических данных трудно писать и читать.
Насколько точно вы смотрите? double / float обеспечивают приличную точность (на мой взгляд). Я почти уверен, что научным / астрономическим данным требуется гораздо больше точности. Я знаю, что библиотеки вроде Matlab и mathematica хороши в этом. Я обнаружил, что вы можете использовать математику со своей программой .net. Вот ссылка
Изменить: добавление дополнительных ссылок и цитат
«Когда система Mathematica работает с рациональными числами, она дает точный результат независимо от того, сколько цифр требуется» из здесь
Другой хорошее чтение , но я думаю, вам придется его реализовать