Minimum price selection for product when database stores the prices in differrent currencies

StackOverflow https://stackoverflow.com/questions/21363820

  •  02-10-2022
  •  | 
  •  

I geather prices for products in different online store which are in United States (us), United Kingdom (uk) and etc. and hold it in one mysql TABLE (com) in local currency. For example, for United States price in US Dollar, for United Kingdom - in GB pound.

TABLE com

 ---------------------------------------------------------------------------------------
| AUTO_INC | COUNTER |   ID |      CONC | VOLUME | PRICE |      SHOP | DATE_G | COUNTRY |
|----------|---------|------|-----------|--------|-------|-----------|--------|---------|
|   115124 |   76720 | 2399 | prod_name |     13 | 34.23 | store1.us |      3 |      us |
|   115186 |   50952 | 2399 | prod_name |     13 |    36 | store2.us |      3 |      us |
|   115187 |   45828 | 2399 | prod_name |     13 | 37.44 | store3.us |      3 |      us |
|   116448 |   73419 | 2399 | prod_name |   11.6 |    48 | store4.us |      3 |      us |
|   116449 |   73421 | 2399 | prod_name |     13 |  65.5 | store4.us |      3 |      us |
|   133334 |   22154 | 2399 | prod_name |     13 | 36.95 | store5.us |      4 |      us |
|   133386 |   31646 | 2399 | prod_name |     13 | 37.44 | store3.us |      4 |      us |
|   134828 |   54667 | 2399 | prod_name |   11.6 |    48 | store4.us |      4 |      us |
|   134929 |   54670 | 2399 | prod_name |     13 |  65.5 | store4.us |      4 |      us |
|   133337 |   22155 | 2399 | prod_name |     13 | 26.95 | store1.uk |      4 |      uk |
|   133387 |   31647 | 2399 | prod_name |     13 | 17.44 | store2.uk |      4 |      uk |
|   134829 |   54668 | 2399 | prod_name |   11.6 |    30 | store3.uk |      4 |      uk |
|   134830 |   54671 | 2399 | prod_name |     13 |  45.5 | store4.uk |      4 |      uk |
 ---------------------------------------------------------------------------------------

To convert prices from local currencies to US dollar I have created TABLE my_currency

TABLE my_currency

 --------------------------------------
| AUTO_INC | DOMAIN | EX_RATE | DATE_G |
|----------|--------|---------|--------|
|      235 |     uk |  0.6066 |      4 |
|      236 |     us |       1 |      4 |
|      237 |     uk |  0.6066 |      3 |
|      238 |     us |       1 |      3 |
 --------------------------------------

If I want to select minimum prices for us online stores (where COUNTRY = 'us'), I use the following query:

SELECT t1.* FROM com as t1
INNER JOIN (
  SELECT id, conc, volume, min(price) as usd_price, date_g 
  FROM com 
  WHERE id=2399 AND date_g=4 AND country='us'
  GROUP BY conc, volume) as t2 
ON t1.conc=t2.conc and t1.volume=t2.volume and t1.id=t2.id and t1.price=t2.usd_price and t1.date_g=t2.date_g
ORDER BY conc DESC, volume DESC

And I get CORRECT result:

| AUTO_INC | COUNTER |   ID |      CONC | VOLUME | PRICE |      SHOP | DATE_G | COUNTRY |
|----------|---------|------|-----------|--------|-------|-----------|--------|---------|
|   133334 |   22154 | 2399 | prod_name |     13 | 36.95 | store5.us |      4 |      us |
|   134828 |   54667 | 2399 | prod_name |   11.6 |    48 | store4.us |      4 |      us |

But now my goal is to select minimum price from all stores (country in ('us', 'uk')) and take into account that database holds prices in local currencies: 1. convert prices from local currencies to us dollar 2. select minimum prices in us dollar

So I tried to use the following query:

SELECT t1.auto_inc, t1.id, t1.conc, t1.volume, (t1.price / my_currency.ex_rate) as sub_price, t1.date_g 
FROM com as t1
 inner join my_currency 
 ON t1.country=my_currency.domain AND t1.date_g=my_currency.date_g
inner join (
 select com.id, com.conc, com.volume, min(com.price / my_currency.ex_rate) as usd_price, com.date_g 
 from com 
 inner join my_currency 
 ON com.country=my_currency.domain AND com.date_g=my_currency.date_g
 WHERE com.id=2399 AND com.date_g=4 AND com.country in ('us', 'uk')
 GROUP BY conc, volume) as t2 
on 
t1.id=t2.id and 
t1.conc=t2.conc and 
t1.volume=t2.volume and 
(t1.price / my_currency.ex_rate)=t2.usd_price and
t1.date_g=t2.date_g 
ORDER BY conc DESC, volume DESC

But I get INCORRECT result:

| AUTO_INC |   ID |      CONC | VOLUME | SUB_PRICE | DATE_G |
|----------|------|-----------|--------|-----------|--------|
|   134828 | 2399 | prod_name |   11.6 |        48 |      4 |

CORRECT result is:

| AUTO_INC |   ID |      CONC | VOLUME | SUB_PRICE | DATE_G |
|----------|------|-----------|--------|-----------|--------|
|   134828 | 2399 | prod_name |   11.6 |        48 |      4 |
|----------|------|-----------|--------|-----------|--------|
|   133387 | 2399 | prod_name |   13   | 28.750412 |      4 |

Does anybody have any ideas? sqlfiddle.com

有帮助吗?

解决方案

The problem is the join on the calculated decimal value. The following works:

SELECT t1.auto_inc, t1.id, t1.conc, t1.volume,
       (t1.price / my_currency.ex_rate) as sub_price, t1.date_g 
FROM com as t1 inner join
     my_currency 
     ON t1.country = my_currency.domain AND t1.date_g = my_currency.date_g
     inner join
     (select com.id, com.conc, com.volume, min(com.price / my_currency.ex_rate) as usd_price, com.date_g 
      from com inner join
           my_currency 
           ON com.country = my_currency.domain AND
              com.date_g = my_currency.date_g
      WHERE com.id=2399 AND com.date_g = 4 AND
            com.country in ('us', 'uk')
      GROUP BY com.id, com.conc, com.volume
     ) as t2 
     on t1.id = t2.id and 
        t1.conc = t2.conc and 
        t1.volume = t2.volume and 
        abs((t1.price / my_currency.ex_rate) - t2.usd_price) < 0.01 and
        t1.date_g = t2.date_g
ORDER BY conc DESC, volume DESC;

However, if you change the join condition on price to:

        t1.price / my_currency.ex_rate =  t2.usd_price and

Then it doesn't work.

It does work if you cast both results back to decimal(10, 2):

        cast(t1.price / my_currency.ex_rate as decimal(10, 2)) = cast(t2.usd_price as decimal(10, 2))

It might have something to do with this note in the documentation:

In division performed with /, the scale of the result when using two exact-value operands is the scale of the first operand plus the value of the div_precision_increment system variable (which is 4 by default). For example, the result of the expression 5.05 / 0.014 has a scale of six decimal places (360.714286)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top