按客户ID更新日期差列时Update语句报错求助
解决按客户分组计算距上一订单天数的更新报错问题
需求说明
按customer_id分组,更新临时表#tmp的TimeToPreviousOrder列,规则如下:
- 当
STANDVALUE=1时,TimeToPreviousOrder=0 - 当
STANDVALUE=2时,TimeToPreviousOrder为当前订单日期与该客户最早订单日期的天数差
初始表
| 客户ID(customer_id) | 订单日期(order_date) | 订单编号(Order No) | 标准值(STANDVALUE) |
|---|---|---|---|
| 1234 | 2019-05-11 00:00:00.000 | 1833322 | 1 |
| 1234 | 2019-05-11 00:00:00.000 | 1833322 | 1 |
| 1234 | 2019-05-29 00:00:00.000 | 1833322 | 2 |
| 4321 | 2019-06-29 00:00:00.000 | 1844415 | 1 |
| 4321 | 2019-06-29 00:00:00.000 | 1844415 | 1 |
| 4321 | 2019-06-30 00:00:00.000 | 1844415 | 2 |
| 8765 | 2019-03-16 00:00:00.000 | 1866615 | 1 |
| 8765 | 2019-06-16 00:00:00.000 | 1866615 | 1 |
| 8765 | 2019-06-16 00:00:00.000 | 1866615 | 1 |
| 8765 | 2019-07-05 00:00:00.000 | 1866615 | 2 |
预期结果
| 客户ID(customer_id) | 订单日期(order_date) | 订单编号(Order No) | 距上一订单天数(TimeToPreviousOrder) | 标准值(STANDVALUE) |
|---|---|---|---|---|
| 1234 | 2019-05-11 00:00:00.000 | 1833322 | 0 | 1 |
| 1234 | 2019-05-11 00:00:00.000 | 1833322 | 0 | 1 |
| 1234 | 2019-05-29 00:00:00.000 | 1833322 | 18 | 2 |
| 4321 | 2019-06-29 00:00:00.000 | 1844415 | 0 | 1 |
| 4321 | 2019-06-29 00:00:00.000 | 1844415 | 0 | 1 |
| 4321 | 2019-06-30 00:00:00.000 | 1844415 | 1 | 2 |
| 8765 | 2019-03-16 00:00:00.000 | 1866615 | 0 | 1 |
| 8765 | 2019-06-16 00:00:00.000 | 1866615 | 0 | 1 |
| 8765 | 2019-06-16 00:00:00.000 | 1866615 | 0 | 1 |
| 8765 | 2019-07-05 00:00:00.000 | 1866615 | 111 | 2 |
错误SQL及报错信息
错误SQL
update #tmp set TimeToPreviousOrder=(select DATEDIFF(day, COALESCE(v.order_date, u.order_date), u.order_date) new_TimeToPreviousOrder from #tmp u OUTER APPLY(SELECT TOP(1) v.order_date FROM #tmp v WHERE v.customer_id = u.customer_id AND v.order_date < u.order_date ORDER BY v.order_date DESC) v ORDER BY u.customer_id,u.order_date )
报错信息
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
问题分析与解决方案
问题原因
- 子查询中包含
ORDER BY但未搭配TOP/OFFSET,违反SQL语法规则; - 子查询返回多行结果,无法直接赋值给单个列,逻辑错误。
正确实现代码
使用CTE结合窗口函数计算目标值,再关联更新临时表:
WITH CalculatedData AS ( SELECT customer_id, [Order No], order_date, STANDVALUE, CASE WHEN STANDVALUE = 1 THEN 0 ELSE DATEDIFF(day, MIN(order_date) OVER (PARTITION BY customer_id), order_date) END AS TargetTime FROM #tmp ) UPDATE t SET t.TimeToPreviousOrder = cd.TargetTime FROM #tmp t JOIN CalculatedData cd ON t.customer_id = cd.customer_id AND t.[Order No] = cd.[Order No] AND t.order_date = cd.order_date AND t.STANDVALUE = cd.STANDVALUE;
代码说明
MIN(order_date) OVER (PARTITION BY customer_id):按客户分组,获取该客户的最早订单日期;CASE语句:根据STANDVALUE的值设置对应的天数,STANDVALUE=1时直接设为0,STANDVALUE=2时计算与最早订单日期的天数差;- 通过CTE计算出每个记录的目标值后,关联临时表进行更新,确保每条记录都被正确赋值。
内容的提问来源于stack exchange,提问作者Robocop
相关产品推荐
相关产品推荐

