Как лучше всего представить рациональные числа в SQL Server? - PullRequest
5 голосов
/ 19 декабря 2009

Я работаю с данными, которые изначально представлены в виде рациональных чисел. У меня есть классный универсальный класс C #, который прекрасно представляет эти данные в C # и позволяет конвертировать во многие другие формы. К сожалению, когда я оборачиваюсь и хочу сохранить это в SQL, я имею в виду пару решений, но ни одно из них не приносит большого удовлетворения.

Вот пример. У меня есть необработанное значение 2/3, которое мой new Rational<int>(2, 3) легко обрабатывает в C #. Варианты, о которых я подумал для хранения этого в базе данных, следующие:

  1. Так же, как десятичная / с плавающей запятой, т. Е. Значение = 0.66666667 различной точности и точности. Плюсы: это позволяет мне запрашивать данные, например, найти значения Минусы: он имеет потерю точности, и это ужасно, когда я возвращаю это простое значение обратно в пользовательский интерфейс.

  2. Хранить как два точных целочисленных поля, например, числитель = 2, знаменатель = 3 различной точности и точности. Плюсы: Это позволяет мне точно представлять исходное значение и отображать его в простейшем виде позже. Минусы: Теперь у меня есть два поля для представления этого значения, и запрос теперь сложен / менее эффективен, поскольку каждый запрос должен выполнять арифметику, например, найти числитель / знаменатель <1. </p>

  3. Сериализация в виде строковых данных, т.е. "2/3". Я был бы в состоянии знать максимальную длину строки и иметь varchar, который мог бы держать это. Плюсы: Я вернулся к одному полю, но с точным представлением. Минусы: Запросы в значительной степени разрушены и оплачивают сериализацию.

  4. Комбинация № 1 и № 2. Плюсы: легко / эффективно запрашивает диапазоны значений, и имеют точные значения в пользовательском интерфейсе. Минусы: три поля (!?!) Для хранения одного фрагмента данных, должны синхронизировать несколько представлений, что прерывает D.R.Y.

  5. Сочетание № 1 и № 3. Плюсы: легко / эффективно запрашивает диапазоны значений, и имеют точные значения в пользовательском интерфейсе. Минусы: возврат к двум полям для хранения данных одного элемента, синхронизация нескольких представлений, что нарушает D.R.Y., и дополнительные расходы на сериализацию.

У кого-нибудь есть другое готовое решение, которое лучше этих? Есть ли другие вещи, которые я не рассматриваю? Есть ли относительно простой способ сделать это в SQL, о котором я просто не знаю?

Ответы [ 5 ]

7 голосов
/ 19 декабря 2009

Если вы используете SQL Server 2005 или 2008, у вас есть возможность определить свои собственные типы данных CLR :

Начиная с SQL Server 2005, вы может использовать пользовательские типы (UDT) для расширить скалярную систему типов сервер, позволяющий хранить CLR объекты в базе данных SQL Server. Пользовательские типы может содержать несколько элементов и может иметь поведение, дифференцируя их из традиционных типов данных псевдонима которые состоят из одного SQL Server системный тип данных.

Поскольку UDT доступны для система в целом, их использование для сложные типы данных могут отрицательно влияние на производительность. Комплексные данные как правило, лучше всего моделируется с помощью традиционные строки и таблицы. UDTs в SQL Server хорошо подходят для следующее:

  • Дата, время, валюта и расширенные числовые типы
  • Геопространственные приложения
  • Кодированные или зашифрованные данные

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

6 голосов
/ 19 декабря 2009

Я бы, вероятно, выбрал вариант № 4, но использовал вычисляемый столбец для 3-го столбца, чтобы избежать проблемы синхронизации / DRY (а также означает, что вы фактически сохраняете только 2 столбца, избегая проблемы «трех полей»). *

На сервере SQL вычисляемый столбец определяется следующим образом:

CREATE TABLE dbo.Whatever(
   Numerator INT NOT NULL,
   Denominator INT NOT NULL,
   Value AS (Numerator / Denominator) PERSISTED
)

(обратите внимание, что вам может потребоваться выполнить какое-то преобразование типов и убедиться, что знаменатель не равен нулю и т. Д.).

Кроме того, в SQL 2005 добавлен вычисляемый столбец PERSISTED, который избавляет от вычислений во время запроса.

2 голосов
/ 19 декабря 2009

Сколько точности вам нужно?

Язык, C # или другой, округлит 2 / 3rds в заданной позиции в точности. Если для того, над чем вы работаете, допустимо использовать десятичные значения, скажем, научной нотации 10, то соответственно установите точность в db.

Если точность действительно важна, то разделите числитель и знаменатель. Это обеспечит вам всегда доступ к любой точности, которую вы хотите, и вы можете использовать вычисляемый столбец для представления значения для быстрой фильтрации:

numerator INT,
denominator INT,
result AS CASE WHEN denominator > 0 THEN numerator / denominator ELSE NULL END
0 голосов
/ 19 декабря 2009

на какую точность вы смотрите? double / float обеспечивают приличную точность (на мой взгляд). Я уверен, что научные / астрономические данные нуждаются в гораздо большей точности, чем это. Я знаю, что такие библиотеки, как matlab и mathematica, хороши в этом. Я обнаружил, что вы можете использовать mathematica с вашей программой .net. Вот ссылка

Редактировать: добавление ссылок и цитат

«Когда Mathematica работает с рациональными числами, она дает точный результат независимо от того, сколько цифр требуется» от здесь

Еще одно хорошее прочтение , но я думаю, вам придется его реализовать

0 голосов
/ 19 декабря 2009

Я немного поэкспериментировал с использованием геометрического типа данных в SQL Server 2008 для хранения и управления рациональными числами. По сути, я предполагаю, что числитель входит в слот X, а знаменатель - в слот Y фиктивной геометрической точки.

Это было хорошо для моих нужд, но может быть бесполезно для ваших. Это будет зависеть от ваших приоритетов (производительность, читаемость кода и т. Д.). Я лично обнаружил, что T-SQL для манипулирования данными геометрии трудно писать и читать.

...