我正在尝试对以下 Customer_Item View 进行一些处理
对于每个客户,我想从他的金额中减去按优先级排序的相关商品的价格,并相应地更新每个商品的状态
如果 IsActiveStore 为 false 或金额为零,则跳过该项目
注释:
- 优先级没有先后顺序,只是按照第二位客户所示的顺序排列
- 如果按优先级订购的任何商品的价格超过客户的金额(减去之前的商品后),则系统将跳过该商品,并继续处理其余优先级的商品,如第二个客户所示<
所以更新后的客户表应该如下
更新后的items表应该如下
现在,我通过使用游标循环遍历客户来完成此操作,对于每个客户,我使用另一个游标循环遍历相关项目,这有效,但对于大数据来说需要很长时间。
有没有更快的替代方法可以有效地进行相同的处理?
提前致谢。
最佳答案
你可以通过CTE来解决它:
WITH cte AS (
SELECT *
FROM
(
VALUES (1, 1000, 1, 100, 1, 1)
, (1, 1000, 2, 200, 1, 2)
, (1, 1000, 3, 300, 0, 3)
, (2, 5000, 4, 1000, 1, 1)
, (2, 5000, 5, 4000, 1, 2)
, (2, 5000, 6, 500, 1, 3)
) t (CustomerId,Amount,ItemId,ItemPrice,IsActiveStore,Priority)
)
, cte2 AS (
SELECT customerid, CASE WHEN amount < itemprice * isActiveStore THEN 0 ELSE amount - itemprice * isActiveStore END AS amount_left, itemId
, 1 AS substracted
, priority
FROM cte
WHERE priority = 1
UNION ALL
SELECT c.customerid, CASE WHEN c2.amount_left < itemprice * isActiveStore THEN 0 ELSE amount_left - itemprice * isActiveStore END AS amount_left, c.itemid
, CASE WHEN c2.amount_left > 0 AND isActiveStore = 1 THEN 1 ELSE 0 END
, c.priority
FROM cte c
INNER JOIN cte2 c2
ON c2.customerid = c.customerid
AND c2.priority = c.priority - 1
)
SELECT customerid, min(amount_left) OVER(partition BY customerid), itemid, CASE substracted WHEN 1 THEN 'substracted' ELSE 'skipped' END
FROM cte2
OPTION(MAXRECURSION 0)
虽然我不确定它是否会比光标更快,但至少在优先级索引不正确的情况下不会。
CTE 本身非常标准,您创建一个初始金额,然后计算每行的差异。
关于sql - 用替代方案替换 SQL Cursor 以提高性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76972726/