Mysql 基于红移或排名分配特定值
我有一张桌子,如图所示。该表有5列, 交易的时间, 客户识别码, 订单号:, 订单价值和 符合条件的折扣 合格的折扣仅为订单价值的10%。 现在我想根据客户的交易时间给他们打折扣,但折扣是 每个客户最多20美元。数据中的适用折扣是我要计算的列。 我使用以下代码根据客户id和交易时间对数据进行排序,但我不知道如何计算适用的折扣列。需要帮助为红移生成查询Mysql 基于红移或排名分配特定值,mysql,sql,postgresql,amazon-redshift,Mysql,Sql,Postgresql,Amazon Redshift,我有一张桌子,如图所示。该表有5列, 交易的时间, 客户识别码, 订单号:, 订单价值和 符合条件的折扣 合格的折扣仅为订单价值的10%。 现在我想根据客户的交易时间给他们打折扣,但折扣是 每个客户最多20美元。数据中的适用折扣是我要计算的列。 我使用以下代码根据客户id和交易时间对数据进行排序,但我不知道如何计算适用的折扣列。需要帮助为红移生成查询 +---------------------+-------------+------------+-------------+---------
+---------------------+-------------+------------+-------------+-------------------+---------------------+
| Time_of_transaction | Customer_id | Order_id | Order_Value | Eligible_discount | Applicable_Discount |
+---------------------+-------------+------------+-------------+-------------------+---------------------+
| 11/1/2019 12:34 | 1234 | 8682686399 | 100 | 10 | 10 |
| 11/2/2019 12:14 | 1234 | 144141455 | 20 | 2 | 2 |
| 11/5/2019 22:14 | 1234 | 1424535235 | 45 | 4.5 | 4.5 |
| 11/7/2019 9:14 | 1234 | 463637675 | 65 | 6.5 | 3.5 |
| 11/7/2019 10:20 | 1234 | 12242144 | 30 | 3 | 0 |
| 11/7/2019 18:10 | 1234 | 141351555 | 80 | 8 | 0 |
| 12/1/2019 12:34 | 5678 | 124421552 | 230 | 23 | 20 |
| 12/2/2019 12:14 | 5678 | 357757757 | 130 | 13 | 0 |
| 12/5/2019 22:14 | 5678 | 28668890 | 80 | 8 | 0 |
| 12/7/2019 9:14 | 5678 | 68568889 | 120 | 12 | 0 |
| 12/7/2019 10:20 | 5678 | 314124455 | 45 | 4.5 | 0 |
+---------------------+-------------+------------+-------------+-------------------+---------------------+
订单级别的20美元上限
计算您的适用折扣应该是最小值(订单价值*0.1,20)
,即您的订单价值*10%上限为20
select Time_of_transaction, Customer_id, Order_id,Order_Value,
0.1*Order_Value as Eligible_discount,
row_number() over
(partition by Customer_id
order by Time_of_transaction asc) as row
from cust_tran_info
order by 2,1
见演示
20美元上限适用于用户级别
如果对另一个答案的评论表明,您希望在用户级别而不是订单级别累积施加20美元的上限,那么您应该使用此选项:
select Time_of_transaction,
Customer_id,
Order_id,
Order_Value,
least(Order_Value * 0.1, 20) as Applicable_Discount,
row_number() over (partition by Customer_id order by Time_of_transaction asc) as row
from cust_tran_info
order by 2,1
见演示。一开始这看起来可能有点混乱,但基本上是计算所有以前订单(不包括当前订单)的折扣总额,以确定当前订单的20美元上限(如果有的话)还有多少剩余
完整sql:
least(Order_Value * 0.1, greatest(0, 20 - coalesce(sum(Order_Value) over(partition by Customer_id order by Time_of_transaction asc ROWS between UNBOUNDED PRECEDING and 1 PRECEDING) * 0.1, 0)))
您可以在子查询中使用窗口和,在外部查询中使用算术逻辑,如下所示:
select Time_of_transaction,
Customer_id,
Order_id,
Order_Value,
row_number() over (partition by Customer_id order by Time_of_transaction asc) Customer_Order_Sequence,
least(Order_Value * 0.1, greatest(0, 20 - coalesce(sum(Order_Value) over(partition by Customer_id order by Time_of_transaction asc ROWS between UNBOUNDED PRECEDING and 1 PRECEDING) * 0.1, 0))) discount_to_be_given_on_current_order
from cust_tran_info
order by 2,1
mysql还是postgresql?这似乎是你最不想要的
LEAST(0.1*stuff,20)
,再说一次,我忍不住觉得这些检查很有用unnecessary@Strawberry:据我所知,OP希望每位客户的累计折扣总额不超过20,因此least()
在这里似乎不是一个选项。您可能是对的,但至少在那个时刻仍然可以使用min。这不是min的工作方式。请在发布之前测试代码。@谢谢您的评论,我们已经解决了这个问题。我的意思是输入LEAST而不是MIN。现在在上面的链接中也进行了测试。@仅供参考,我再次更新了我的答案,以包含一个解决方案,以防该人员希望在用户级别而不是订单级别设置上限。我无法对另一个答案发表评论:/
select
t.*,
case
when coalesce(sum_discount, 0) > 20 then 0
when sum_discount + order_value * 0.1 > 20 then 20 - sum_discount
else order_value * 0.1
end applicable_discount
from (
select
t.*,
sum(order_value * 0.1) over(
partition by customer_id
order by time_of_transaction
rows between unboundeed preceding and 1 preceding
) sum_discount
from mytable t
) t