使用来自其他表的汇率将价格转换为总和并计算平均值。

huangapple go评论94阅读模式
英文:

convert prices with exchangerates from other table SUM and get AVG

问题

我的想法是:

服务器:使用最新的MariaDB的Ubuntu

这是一个投资组合算法,用户可以用美元之类的货币购买股票,但他的投资组合可以以欧元计价,因此需要将价值转换。

  1. 我需要一个接近创建日期的汇率,如果没有,则使用之前的日期的汇率。
  2. 将剩余金额乘以转换为我想要的货币的价格求和(在这种情况下,为了更容易理解,它将是1的汇率,目标货币将通过查询提供,在这种情况下是2)。
  3. 结果应该除以剩余金额的总和,以获得正确的购买价格,即平均价格。

我已经更新了数据,以使测试更简单,例如,源货币现在与目标货币相同,因此计算是1:1的。

SQL Fiddle在这里:http://sqlfiddle.com/#!9/8c7fc59/11
运行针对我的数据库的查询的结果:

https://pastebin.com/pSerHN0j

前两个结果是我想要的,第三个来自jmvcollaborator,其中平均买入价格是正确的,但金额加倍了。

具有更多数据的SQL导出:

https://pastebin.com/d1aVX2wm

更新的问题:

子查询的解决方案有效,但性能不是最佳的,所以我目前正在寻找一个没有子查询的解决方案。

在我的信息分区之后,应该有一个解决方案,但这不是我的专业知识,所以也许有人可以在这里帮助我。

英文:

What my idea is:

Server: Ubuntu with latest MariaDB

It's a portfolio algo, the user can buy stocks in a currency like USD but his portfolio can be in EURO, so the values must be converted.

  1. I need a exchange rate near the created date, if not use a rate from date before.
  2. SUM the amounts_lefts * price converted to currency i want (in this case for easier understand it will be a rate of 1, the target currency will submit over query in this case 2.
  3. the result should be divides though the sum of amounts_left to get the correct buyIN aka AVG price.

Ive updated the data to make things more simple for test, like currency of source is now the same as target, so the calculation is 1:1

  1. SQL Fiddle is here: http://sqlfiddle.com/#!9/8c7fc59/11
  2. Results running against my DB with querys
  3. https://pastebin.com/pSerHN0j

the first 2 results are what i want, the 3. one is from jmvcollaborator where the AVG BuyIN is correct but the amounts are doubled

  1. SQL Export with more Data
  2. https://pastebin.com/d1aVX2wm

Updated Question:

The solution over Subquery is working, but this Method is not the best in performance, so im currently looking for a solution without this.

After my Information partitions over should be here a solution, but this is not my kind of knowledge, so maybe anyone can help me here.

答案1

得分: 1

以下是您要翻译的内容:

  1. 我会在这里写一些发现,首先我想要双重确认你的第一个查询是否有效,请确认:
  2. SELECT SUM(amounts_left*price)/SUM(amounts_left) as eBuyIN
  3. FROM transactions as t
  4. WHERE 1 GROUP BY currency_id,broker_id,portfolio_id,instrument_id;
  5. 如果不起作用,那么让我分享一些有关我们已经使其工作的查询的发现:
  6. SELECT
  7. SUM(price)/SUM(mleft)
  8. FROM(
  9. SELECT
  10. `instrument_id`,
  11. amounts_left AS mleft,
  12. amounts_left * price * (
  13. SELECT `rate`
  14. FROM `currency_exchanges`
  15. WHERE `from_currency_id` = t.currency_id
  16. AND `to_currency_id` = 2
  17. AND `date` <= t.created
  18. ORDER BY `date` DESC LIMIT 1
  19. ) AS price
  20. FROM `transactions` AS `t`
  21. WHERE `action` = 1
  22. AND `portfolio_id` = 128
  23. ) a
  24. 查询成本为2.72,因为它执行了全表扫描,由于嵌套查询。我尝试了一种不同的方法,使用CTEOVER PARTITION BY,查询成本为0.35,由于分区内的列是非唯一键查找,因此比以前的查询要快得多,下面是CTE代码
  25. WITH
  26. cte AS (
  27. SELECT ROW_NUMBER() OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id ORDER BY amounts_left DESC
  28. ) AS rowNumber,
  29. SUM(amounts_left) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id
  30. ORDER BY amounts_left DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS amountsleftT,
  31. SUM(amounts_left*price) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id
  32. ORDER BY amounts_left DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS priceT
  33. FROM currency_exchanges AS ce
  34. JOIN transactions AS t
  35. ON from_currency_id = t.currency_id
  36. AND to_currency_id = 2
  37. AND ce.date <= t.created
  38. AND action = 1 and portfolio_id = 128
  39. )
  40. Select priceT/amountsleftT as Total from cte where rowNumber = 1;
  41. 我建议添加更多数据,以便可以测试许多不同的情况,您可以继续在fiddle上工作并分享链接
  42. 希望我有些帮助。
  43. **更新** 使用Over Partition By的查询已更新,因为聚合错误。**重要提示**:性能仍然优于其他方法。以下是有效的查询:
  44. WITH cte AS
  45. (
  46. select
  47. instrument_id,
  48. ROW_NUMBER() OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) AS rowNumber,
  49. Sum(amounts_left* price *ce.rate) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) AS priceSum,
  50. Sum(amounts_left) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) amountsleftSum
  51. from transactions t left join
  52. (select ce.*, row_number() over (partition by from_currency_id order by date desc) as seqnum
  53. from currency_exchanges ce
  54. where
  55. to_currency_id = 2
  56. order by ce.date desc
  57. ) ce
  58. on ce.from_currency_id = t.currency_id and seqnum = 1
  59. WHERE
  60. ce.date <= t.created
  61. AND action = 1 AND amounts_left > 0 AND portfolio_id = 128
  62. )
  63. SELECT
  64. priceSum/amountsleftSum as eBuyIN,
  65. amountsleftSum AS amounts_left,
  66. instrument_id
  67. FROM cte
  68. WHERE rownumber = 1;

希望这有所帮助。

英文:

I will write some findings here, first i would like to double check that your very first query works, please confirm:

  1. SELECT SUM(amounts_left*price)/SUM(amounts_left) as eBuyIN
  2. FROM transactions as t
  3. WHERE 1 GROUP BY currency_id,broker_id,portfolio_id,instrument_id;

If it does not work then let me share some findings with regards of the query we got working which is:

  1. SELECT
  2. SUM(price)/SUM(mleft)
  3. FROM(
  4. SELECT
  5. `instrument_id`,
  6. amounts_left AS mleft,
  7. amounts_left * price * (
  8. SELECT `rate`
  9. FROM `currency_exchanges`
  10. WHERE `from_currency_id` = t.currency_id
  11. AND `to_currency_id` = 2
  12. AND `date` <= t.created
  13. ORDER BY `date` DESC LIMIT 1
  14. ) AS price
  15. FROM `transactions` AS `t`
  16. WHERE `action` = 1
  17. AND `portfolio_id` = 128
  18. ) a

The query cost is 2.72 since it perform a full table scan due the nested query. I took the freedom to try a different approach using CTE and OVER PARTITION BY and the query cost is 0.35 a non unique key look up due the columns inside the partition thus much faster that the previous query, here is the CTE code:

  1. WITH
  2. cte AS (
  3. SELECT ROW_NUMBER() OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id ORDER BY amounts_left DESC
  4. ) AS rowNumber,
  5. SUM(amounts_left) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id
  6. ORDER BY amounts_left DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS amountsleftT,
  7. SUM(amounts_left*price) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id
  8. ORDER BY amounts_left DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS priceT
  9. FROM currency_exchanges AS ce
  10. JOIN transactions AS t
  11. ON from_currency_id = t.currency_id
  12. AND to_currency_id = 2
  13. AND ce.date <= t.created
  14. AND action = 1 and portfolio_id = 128
  15. )
  16. Select priceT/amountsleftT as Total from cte where rowNumber = 1;

I would suggest to add more data so many different cases can be tested you can keep working on the fiddle and share the link.

Hopefully i have helped somehow.

UPDATE query with Over Partition By was updated cause the aggregates were wrong. IMPORTANT: still the performance is better than the other approaches.
Here is the working query:

  1. WITH cte AS
  2. (
  3. select
  4. instrument_id,
  5. ROW_NUMBER() OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) AS rowNumber,
  6. Sum(amounts_left* price *ce.rate) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) AS priceSum,
  7. Sum(amounts_left) OVER(PARTITION BY t.currency_id,t.broker_id,t.portfolio_id,t.instrument_id) amountsleftSum
  8. from transactions t left join
  9. (select ce.*, row_number() over (partition by from_currency_id order by date desc) as seqnum
  10. from currency_exchanges ce
  11. where
  12. to_currency_id = 2
  13. order by ce.date desc
  14. ) ce
  15. on ce.from_currency_id = t.currency_id and seqnum = 1
  16. WHERE
  17. ce.date <= t.created
  18. AND action = 1 AND amounts_left > 0 AND portfolio_id = 128
  19. )
  20. SELECT
  21. priceSum/amountsleftSum as eBuyIN,
  22. amountsleftSum AS amounts_left,
  23. instrument_id
  24. FROM cte
  25. WHERE rownumber = 1;

huangapple
  • 本文由 发表于 2023年5月28日 23:22:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定