Мультивалютная информационная система, неточность SQL
Я работаю над созданием информационной системы, которая должна работать с несколькими валютами ( USD, EUR, JPY). Допустим, пользователь может добавлять продукты в систему. Пользователь добавляет продукт #1 13 февраля 2017, цена 2000, валюта JPY. Пользователь добавляет товар #2 14 февраля 2017, цена 25, валюта USD.
Позже (15 февраля 2017 г.) пользователь может просматривать и фильтровать свои продукты, скажем, пользователь хочет просматривать продукты в долларах США, и существует фильтр ценового диапазона.
Цель:
- пользователь устанавливает некоторый ценовой диапазон, и я должен найти эти продукты в базе данных должным образом
Мой текущий подход:
- я решил, что евро - это моя единая валюта
- когда пользователь добавляет продукт - конвертируйте цену каждого продукта в евро по текущему обменному курсу
- в базе данных сохраняется исходная цена и валюта (из пользовательского ввода), конвертированная цена (EUR)
- диапазон цен в фильтре инициализируется по сегодняшнему курсу, поэтому 2000 иен конвертируется в доллары США как нижний предел (17.5 долларов США), 20 долларов США - как верхний предел
Проблемы:
- пользователь устанавливает лимит от 17,5 до 20 долларов
- Я конвертирую 17,5 долларов США в EUR_value_1, 20 долларов США в EUR_value_2
- выберите базу данных, где Price_unified между EUR_value_1 и EUR_value_2
- значения не соответствуют продуктам в базе данных, потому что используемый показатель может быть выше / ниже (каждый день), поэтому значения различны
Мои вопросы:
- Как правильно хранить эти продукты, цены, валюты в базе данных? Должен ли я хранить все значения валюты?
- Как обработать поведение внешнего интерфейса в качестве фильтра ценового диапазона в некоторой валюте, но при этом иметь возможность правильно находить товары в базе данных?
- Должен ли я создать крон, чтобы преобразовать все цены по сегодняшнему курсу?
2 ответа
Таблицы курсов валют распространены в международных финансовых приложениях. Обычно все указывается как отношение к одной валюте, например доллару США. Для каждой валюты в день требуется только одна запись, обычно курс закрытия предыдущего дня - за исключением базовой валюты, которая всегда равна 1. Вот так:
Effective Code Factor
2015-05-02 GBP 0.662251656 --based on today's rate of 1.51 GBP->USD
Чтобы перейти от USD к GBP: USD * фактор = GBP
Чтобы перейти от GBP к USD: GBP / фактор = USD
Здесь представлена слайд-презентация, на которой показан такой дизайн стола. Обсуждение валюты начинается на слайде / странице 12, запрос на странице 16. Дизайн таблицы прост:
create table XRates(
Code char( 3 ) not null,
Effective date not null,
Factor decimal( 12, 9 ) not null
constraint PK_XRates primary key( Code, Effective )
);
Пара приятных особенностей дизайна заключается в том, что вы сохраняете исторические курсы в той же таблице, что и текущий курс, и ежедневные обновления не нужны. Запись делается только при изменении скорости или когда скорость изменяется достаточно, чтобы вызвать обновление. Запрос возвращает курс, действовавший на указанную дату, даже если этот курс был установлен недельной записью (вряд ли на сегодняшних валютных рынках).
Конечно, вы бы указали в качестве базовой валюты евро, но дизайн таблицы и запрос не изменились бы.
Таким образом, вам нужно только хранить цену и валюту продукта. Цена в евро на продукт, который был оценен в 2000 иен, может быть легко конвертирована в соответствии с курсом, действующим, например, в день размещения заказа.
Сохраните первоначальную цену в оригинальной валюте. Ваш последний вопрос - деловое, а не техническое решение, поэтому не ожидайте ответа здесь.
Опция 1
Чтобы сделать это гибким способом, я бы предложил вам создать отдельную структуру таблиц для хранения курсов валют. Создайте функцию, которая будет возвращать структуру таблицы с обменными курсами на доступную валюту. Таким образом, вы можете легко отказаться от использования ставок за день или чего-либо еще - вы изолируете эту логику с минимальной ценой производительности.
Следующим шагом является создание SP для запроса результатов. Особое замечание здесь заключается в том, что вы должны изменить границы, по которым вы ищете, вместо фактического значения, чтобы вы все еще могли использовать индексы в таблице. Результат функции вы будете использовать для создания таблицы, которая будет содержать валюту и скорректированы границы для этой валюты. Вы присоединитесь к этому столу.
Я могу опубликовать пример, если вам нужен - поднять ответ или написать комментарий, если это так.
Вариант 2
Если вам не нужна гибкость или вы редко меняете обменные курсы - снова сохраните цену в исходной валюте, но также рассчитайте и сохраните цену в единой валюте. Вы можете сделать это в отдельной таблице или в новом столбце, если вам не нужна нормализация. Опять же, выполните поиск, изменив границы и сравнив их с предварительно вычисленной единой ценой, чтобы использовать индексы