Postgresql:计算每个投资者每天的总投资份额
Postgresql: calculate share of total investment per investor, per day
注意:我在整个过程中使用 Y-m-d 日期格式 post。
所以我有一个包含三个 table 的数据库:
投资者、投资、daily_stats
我已经在这个 db-fiddle 中设置了它们:https://www.db-fiddle.com/f/m1DFJKzMs8SuYeVAUYcHU9/6
投资者基本上就是我的“用户”table。它包含投资者详细信息,例如电子邮件、姓名等。
在 investments table 中,我正在存储每个投资者投资的数据。 start_date 是投资开始的时间,end_date 是投资结束的时间,amount 是投资多少,percent 是投资者从他的投资中获得的利润份额。 (其余费用自理)
并且在我的 daily_stats table 中,我有每天所有活跃投资总和的每日总利润。
现在,棘手的部分是为每个投资者生成一个数据集,向他们显示他们从所提供的数据中获得的个人投资每日利润。例如:
日期
利润
2021-01-01
3美元
2021-01-02
7 美元
2021-01-03
1美元
2021-01-04
5美元
2021-01-05
9美元
为此,我的查询需要计算投资者在每个每日统计数据中的总投资份额,并将他们的投资百分比应用到利润中。例如,如果您查看 Mike 的投资,您会发现它与属于 John 的其他两项投资相交。我们可以这样想象它:
因此,每个投资者在总投资中所占的份额会根据投资的数量和规模而变化。我们来看一个日期:2021-02-03
在 daily_stats,该日期的利润为 339 美元
当天的总投资为 25000 美元
约翰的份额是 5000 美元 (20%),他的止盈百分比是 20。
Mike 的份额是 20000 美元 (80%),他的止盈百分比是 40。
因此迈克以 339 * 0.8 * 0.4 = 108.48 的成绩回家
约翰拿下 339 * 0.2 * 0.2 = 13.56
现在我想我可以为我想要 select 统计的时间段设置一个 generate_series 并加入 investments/daily_stats table 但是我不确定如何设置它,以便按照演示的方式每天计算投资者的利润
以下内容可以同时应用于所有用户的任何日期范围。在这个特定的 SQL 中,我计算了日期 2021-02-01 到 2021-02-05 之间的 user_profit。
另请注意,我认为您对 John's share is 00 (25%)
的计算不正确。 25000 美元中的 5000 美元是 20%,而不是 25%。同样的问题也适用于 Mike 的份额。因此,以下结果与您的预期结果不完全一致。但我相信这个 SQL 是正确的。
SELECT s.date, s.profit
, i.user_id, i.amount, i.percent
, SUM(i.amount) OVER (PARTITION BY s.date) AS total_inv
, ROUND(s.profit * (i.percent / 100.0) * i.amount / SUM(i.amount) OVER (PARTITION BY s.date), 2) AS user_profit
FROM daily_stats AS s
JOIN investments AS i
ON s.date BETWEEN i.start_date AND i.end_date
WHERE s.date BETWEEN '2021-02-01' AND '2021-02-05'
ORDER BY s.date, i.user_id
;
+------------+--------+---------+--------+---------+-----------+-------------+
| date | profit | user_id | amount | percent | total_inv | user_profit |
+------------+--------+---------+--------+---------+-----------+-------------+
| 2021-02-01 | 248 | 1 | 5000 | 20 | 25000 | 9.92 |
| 2021-02-01 | 248 | 2 | 20000 | 40 | 25000 | 79.36 |
| 2021-02-02 | 476 | 1 | 5000 | 20 | 25000 | 19.04 |
| 2021-02-02 | 476 | 2 | 20000 | 40 | 25000 | 152.32 |
| 2021-02-03 | 339 | 1 | 5000 | 20 | 25000 | 13.56 |
| 2021-02-03 | 339 | 2 | 20000 | 40 | 25000 | 108.48 |
| 2021-02-04 | 464 | 1 | 5000 | 20 | 25000 | 18.56 |
| 2021-02-04 | 464 | 2 | 20000 | 40 | 25000 | 148.48 |
| 2021-02-05 | 156 | 1 | 5000 | 20 | 25000 | 6.24 |
| 2021-02-05 | 156 | 2 | 20000 | 40 | 25000 | 49.92 |
+------------+--------+---------+--------+---------+-----------+-------------+
我也更新了你的 fiddle:
Solution in your fiddle
这里的结果也包括 1 月的日期,显示了不同的 total_investment 这些日期:
+------------+--------+---------+--------+---------+-----------+-------------+
| date | profit | user_id | amount | percent | total_inv | user_profit |
+------------+--------+---------+--------+---------+-----------+-------------+
| 2021-01-28 | 488 | 1 | 10000 | 20 | 30000 | 32.53 |
| 2021-01-28 | 488 | 2 | 20000 | 40 | 30000 | 130.13 |
| 2021-01-29 | 480 | 1 | 10000 | 20 | 30000 | 32.00 |
| 2021-01-29 | 480 | 2 | 20000 | 40 | 30000 | 128.00 |
| 2021-01-30 | 332 | 1 | 10000 | 20 | 30000 | 22.13 |
| 2021-01-30 | 332 | 2 | 20000 | 40 | 30000 | 88.53 |
| 2021-01-31 | 461 | 1 | 10000 | 20 | 30000 | 30.73 |
| 2021-01-31 | 461 | 2 | 20000 | 40 | 30000 | 122.93 |
| 2021-02-01 | 248 | 1 | 5000 | 20 | 25000 | 9.92 |
| 2021-02-01 | 248 | 2 | 20000 | 40 | 25000 | 79.36 |
| 2021-02-02 | 476 | 1 | 5000 | 20 | 25000 | 19.04 |
| 2021-02-02 | 476 | 2 | 20000 | 40 | 25000 | 152.32 |
| 2021-02-03 | 339 | 1 | 5000 | 20 | 25000 | 13.56 |
| 2021-02-03 | 339 | 2 | 20000 | 40 | 25000 | 108.48 |
| 2021-02-04 | 464 | 1 | 5000 | 20 | 25000 | 18.56 |
| 2021-02-04 | 464 | 2 | 20000 | 40 | 25000 | 148.48 |
| 2021-02-05 | 156 | 1 | 5000 | 20 | 25000 | 6.24 |
| 2021-02-05 | 156 | 2 | 20000 | 40 | 25000 | 49.92 |
+------------+--------+---------+--------+---------+-----------+-------------+
注意:我在整个过程中使用 Y-m-d 日期格式 post。
所以我有一个包含三个 table 的数据库:
投资者、投资、daily_stats
我已经在这个 db-fiddle 中设置了它们:https://www.db-fiddle.com/f/m1DFJKzMs8SuYeVAUYcHU9/6
投资者基本上就是我的“用户”table。它包含投资者详细信息,例如电子邮件、姓名等。
在 investments table 中,我正在存储每个投资者投资的数据。 start_date 是投资开始的时间,end_date 是投资结束的时间,amount 是投资多少,percent 是投资者从他的投资中获得的利润份额。 (其余费用自理)
并且在我的 daily_stats table 中,我有每天所有活跃投资总和的每日总利润。
现在,棘手的部分是为每个投资者生成一个数据集,向他们显示他们从所提供的数据中获得的个人投资每日利润。例如:
日期 | 利润 |
---|---|
2021-01-01 | 3美元 |
2021-01-02 | 7 美元 |
2021-01-03 | 1美元 |
2021-01-04 | 5美元 |
2021-01-05 | 9美元 |
为此,我的查询需要计算投资者在每个每日统计数据中的总投资份额,并将他们的投资百分比应用到利润中。例如,如果您查看 Mike 的投资,您会发现它与属于 John 的其他两项投资相交。我们可以这样想象它:
因此,每个投资者在总投资中所占的份额会根据投资的数量和规模而变化。我们来看一个日期:2021-02-03
在 daily_stats,该日期的利润为 339 美元
当天的总投资为 25000 美元
约翰的份额是 5000 美元 (20%),他的止盈百分比是 20。
Mike 的份额是 20000 美元 (80%),他的止盈百分比是 40。
因此迈克以 339 * 0.8 * 0.4 = 108.48 的成绩回家
约翰拿下 339 * 0.2 * 0.2 = 13.56
现在我想我可以为我想要 select 统计的时间段设置一个 generate_series 并加入 investments/daily_stats table 但是我不确定如何设置它,以便按照演示的方式每天计算投资者的利润
以下内容可以同时应用于所有用户的任何日期范围。在这个特定的 SQL 中,我计算了日期 2021-02-01 到 2021-02-05 之间的 user_profit。
另请注意,我认为您对 John's share is 00 (25%)
的计算不正确。 25000 美元中的 5000 美元是 20%,而不是 25%。同样的问题也适用于 Mike 的份额。因此,以下结果与您的预期结果不完全一致。但我相信这个 SQL 是正确的。
SELECT s.date, s.profit
, i.user_id, i.amount, i.percent
, SUM(i.amount) OVER (PARTITION BY s.date) AS total_inv
, ROUND(s.profit * (i.percent / 100.0) * i.amount / SUM(i.amount) OVER (PARTITION BY s.date), 2) AS user_profit
FROM daily_stats AS s
JOIN investments AS i
ON s.date BETWEEN i.start_date AND i.end_date
WHERE s.date BETWEEN '2021-02-01' AND '2021-02-05'
ORDER BY s.date, i.user_id
;
+------------+--------+---------+--------+---------+-----------+-------------+
| date | profit | user_id | amount | percent | total_inv | user_profit |
+------------+--------+---------+--------+---------+-----------+-------------+
| 2021-02-01 | 248 | 1 | 5000 | 20 | 25000 | 9.92 |
| 2021-02-01 | 248 | 2 | 20000 | 40 | 25000 | 79.36 |
| 2021-02-02 | 476 | 1 | 5000 | 20 | 25000 | 19.04 |
| 2021-02-02 | 476 | 2 | 20000 | 40 | 25000 | 152.32 |
| 2021-02-03 | 339 | 1 | 5000 | 20 | 25000 | 13.56 |
| 2021-02-03 | 339 | 2 | 20000 | 40 | 25000 | 108.48 |
| 2021-02-04 | 464 | 1 | 5000 | 20 | 25000 | 18.56 |
| 2021-02-04 | 464 | 2 | 20000 | 40 | 25000 | 148.48 |
| 2021-02-05 | 156 | 1 | 5000 | 20 | 25000 | 6.24 |
| 2021-02-05 | 156 | 2 | 20000 | 40 | 25000 | 49.92 |
+------------+--------+---------+--------+---------+-----------+-------------+
我也更新了你的 fiddle: Solution in your fiddle
这里的结果也包括 1 月的日期,显示了不同的 total_investment 这些日期:
+------------+--------+---------+--------+---------+-----------+-------------+
| date | profit | user_id | amount | percent | total_inv | user_profit |
+------------+--------+---------+--------+---------+-----------+-------------+
| 2021-01-28 | 488 | 1 | 10000 | 20 | 30000 | 32.53 |
| 2021-01-28 | 488 | 2 | 20000 | 40 | 30000 | 130.13 |
| 2021-01-29 | 480 | 1 | 10000 | 20 | 30000 | 32.00 |
| 2021-01-29 | 480 | 2 | 20000 | 40 | 30000 | 128.00 |
| 2021-01-30 | 332 | 1 | 10000 | 20 | 30000 | 22.13 |
| 2021-01-30 | 332 | 2 | 20000 | 40 | 30000 | 88.53 |
| 2021-01-31 | 461 | 1 | 10000 | 20 | 30000 | 30.73 |
| 2021-01-31 | 461 | 2 | 20000 | 40 | 30000 | 122.93 |
| 2021-02-01 | 248 | 1 | 5000 | 20 | 25000 | 9.92 |
| 2021-02-01 | 248 | 2 | 20000 | 40 | 25000 | 79.36 |
| 2021-02-02 | 476 | 1 | 5000 | 20 | 25000 | 19.04 |
| 2021-02-02 | 476 | 2 | 20000 | 40 | 25000 | 152.32 |
| 2021-02-03 | 339 | 1 | 5000 | 20 | 25000 | 13.56 |
| 2021-02-03 | 339 | 2 | 20000 | 40 | 25000 | 108.48 |
| 2021-02-04 | 464 | 1 | 5000 | 20 | 25000 | 18.56 |
| 2021-02-04 | 464 | 2 | 20000 | 40 | 25000 | 148.48 |
| 2021-02-05 | 156 | 1 | 5000 | 20 | 25000 | 6.24 |
| 2021-02-05 | 156 | 2 | 20000 | 40 | 25000 | 49.92 |
+------------+--------+---------+--------+---------+-----------+-------------+