Chcę umożliwić użytkownikom wyszukiwanie produktów w przedziale cenowym. Użytkownik powinien mieć możliwość korzystania z dowolnej waluty (USD, EUR, GBP, JPY, ...), bez względu na walutę ustawioną przez produkt. Cena produktu wynosi 200 USD, a jeśli użytkownik wyszuka produkty kosztujące 100 EUR - 200 EUR, nadal może go znaleźć. Jak zrobić to szybko i skutecznie?
Oto, co zrobiłem do tej pory. Przechowuję price
, currency code
a calculated_price
to jest cena w euro (EUR), która jest domyślną walutą.
CREATE TABLE "products" (
"id" serial,
"price" numeric NOT NULL,
"currency" char(3),
"calculated_price" numeric NOT NULL,
CONSTRAINT "products_id_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "currencies" (
"id" char(3) NOT NULL,
"modified" timestamp NOT NULL,
"is_default" boolean NOT NULL DEFAULT 'f',
"value" numeric NOT NULL, -- ratio additional to the default currency
CONSTRAINT "currencies_id_pkey" PRIMARY KEY ("id")
);
INSERT INTO "currencies" (id, modified, is_default, value)
VALUES
('EUR', '2012-05-17 11:38:45', 't', 1.0),
('USD', '2012-05-17 11:38:45', 'f', '1.2724'),
('GBP', '2012-05-17 11:38:45', 'f', '0.8005');
INSERT INTO "products" (price, currency, calculated_price)
SELECT 200.0 AS price, 'USD' AS currency, (200.0 / value) AS calculated_price
FROM "currencies" WHERE id = 'USD';
Jeśli użytkownik szuka innej waluty, powiedzmy USD, obliczamy cenę w EUR i przeszukujemy calculated_price
kolumnę.
SELECT * FROM "products" WHERE calculated_price > 100.0 AND calculated_price < 200.0;
W ten sposób możemy bardzo szybko porównywać ceny, ponieważ nie musimy obliczać rzeczywistej ceny dla każdego wiersza, ponieważ jest ona obliczana raz.
Złą rzeczą jest to, że przynajmniej codziennie musimy ponownie obliczyć default_price
wszystkie wiersze, ponieważ zmieniono kursy walut.
Czy istnieje lepszy sposób, aby sobie z tym poradzić?
Czy nie ma innego sprytnego rozwiązania? Może jakiś wzór matematyczny? Mam pojęcie, że calculated_price
jest to stosunek do jakiejś zmiennej, X
a kiedy zmienia się waluta, aktualizujemy tylko tę zmienną X
, a nie tę calculated_price
, więc nawet nie musimy niczego aktualizować (wiersze) ... Może jakiś matematyk może to rozwiązać lubię to?
źródło
calculated_price
w ogóle powinienem aktualizować ? Mógłbym po prostu zapisaćinitial_currency_value
(stały, przyjęty, powiedzmy, dzisiaj, kurs walutowy) i zawsze liczyć się z tym! Oczywiście przy wyświetlaniu ceny w euro należy obliczyć rzeczywisty kurs walutowy. Czy mam rację? Czy istnieje problem, którego nie widzę?Wpadłem na własny pomysł. Powiedz mi, czy to naprawdę zadziała, proszę!
Problem.
Po dodaniu produktu do
products
tabeli cena jest konwertowana na domyślną walutę (EUR) i zapisywana wcalculated_price
kolumnie.Chcemy, aby użytkownik mógł wyszukiwać (filtrować) ceny dowolnej waluty. Odbywa się to poprzez konwersję ceny wejściowej na domyślną walutę (EUR) i porównanie jej z
calculated_price
kolumną.Musimy zaktualizować kursy walut, aby użytkownicy mogli wyszukiwać według świeżego kursu walut. Problem polega jednak na tym - jak
calculated_price
skutecznie aktualizować .Rozwiązanie (mam nadzieję).
Nie! :)
Chodzi o to, że bierzemy wczorajsze kursy walut ( wszystkie z tego samego dnia ),
calculated_price
używając tylko tych. Jak zawsze! Brak codziennych aktualizacji. Jedyne, czego potrzebujemy, zanim porównamy / przefiltrujemy / przeszukamy ceny, to przyjąć dzisiejsze kursy walut, tak jak były wczoraj.Tak więc,
calculated_price
użyjemy tylko kursu waluty z ustalonej daty (wybraliśmy, powiedzmy, wczoraj). Będziemy potrzebować przeliczyć dzisiejszą cenę na cenę wczorajszą. Innymi słowy, weź dzisiejszy kurs i przelicz go na wczorajszy kurs:A to jest tabela walut:
W ten sposób można dodać produkt, który kosztuje 200 USD, oraz sposób
calculated_price
obliczenia ceny: od USD do najnowszej stawki EUR i do stałej (starej) stawkiMożna to również wstępnie obliczyć po stronie klienta i to właśnie zamierzam zrobić - obliczyć cenę wejściową użytkownika na
calculated_price
zgodną wartość przed wykonaniem zapytania, aby użyć starego dobregoSELECT * FROM products WHERE calculated_price > 100.0 AND calculated_price < 200.0;
Wniosek.
Ten pomysł przyszedł do mnie zaledwie kilka godzin temu i obecnie proszę o sprawdzenie, czy mam rację co do tego rozwiązania. Co myślisz? Czy to zadziała? Czy myliłem się?
Mam nadzieję, że to wszystko rozumiesz. Nie jestem rodzimym językiem angielskim, jest też późno i jestem zmęczony. :)
AKTUALIZACJA
Wygląda na to, że rozwiązuje jeden problem, ale wprowadza inny. Szkoda :)
źródło
rate_newest / rate_fixed
różnią się one w zależności od waluty, a to rozwiązanie uwzględnia tylko pieniądze wybrane przez użytkownika podczas wyszukiwania. Żadna cena w innej walucie nie byłaby porównywana z aktualnymi kursami. Odpowiedź, którą przesłałem, miała podobny problem, ale myślę, że naprawiłem ją w zaktualizowanej wersji.