DECLARE @DACTUALWEIGHT DEC(18,3),@DHIGHWEIGHT DEC(18,3) WITH SalesData AS ( SELECT B.DITEMCODE,B.DCOLORCODE,B.DCOLORNAME,SUM(B.DLENGTH) AS DLENGTH FROM SM_SaleOrder A INNER JOIN SM_SaleOrderDts B ON A.DSYSID = B.DSYSID WHERE (A.DISSTORE=1 OR DPTNCODE='M-SXYS-00623') AND A.DSTATERUN IN(12,13) AND A.DMODULENO='210101' AND A.DSYSID=1112194 GROUP BY B.DITEMCODE, B.DCOLORCODE, B.DCOLORNAME ), StockData AS ( SELECT A.DITEMCODE,A.DCOLORCODE,A.DCOLORNAME,SUM(A.DLENGTH) AS DLENGTH FROM WM_Stock A INNER JOIN SM_SaleOrderDts B ON A.DITEMCODE=B.DITEMCODE AND A.DCOLORCODE=B.DCOLORCODE AND A.DCOLORNAME=B.DCOLORNAME AND B.DSYSID=1112194 WHERE DWHTYPE=4 AND DWHCODE IN ('C03','C06') AND DSSALEOPID='综合部' GROUP BY A.DITEMCODE,A.DCOLORCODE,A.DCOLORNAME ) SELECT @DACTUALWEIGHT=SUM(C.DLENGTH),@DHIGHWEIGHT=SUM(A.DHIGHWEIGHT) FROM WM_SafeStockDts A INNER JOIN SalesData B ON A.DITEMCODE=B.DITEMCODE AND A.DCOLORCODE=B.DCOLORCODE AND A.DCOLORNAME=B.DCOLORNAME LEFT JOIN StockData C ON A.DITEMCODE=C.DITEMCODE AND A.DCOLORCODE=C.DCOLORCODE AND A.DCOLORNAME=C.DCOLORNAME IF @DACTUALWEIGHT+@DLENGTHSUM>@DHIGHWEIGHT BEGIN SET @DAUDITPROMTS+='l、该订单的订单量('+CAST(@DLENGTHSUM AS VARCHAR(20))+ 'kg)加上当前库存('+CAST(@DACTUALWEIGHT AS VARCHAR(20))+ 'kg),将会超出库存预警上限('+CAST(@DHIGHWEIGHT AS VARCHAR(20))+ 'kg)'+CHAR(13)+CHAR(10) END优化一下
时间: 2025-07-13 15:44:00 浏览: 5
<think>好的,我现在需要帮助用户优化他们提供的SQL代码。首先,我得仔细阅读并理解这段代码的功能。看起来这是一个存储过程的一部分,用于检查订单量加上当前库存是否会超过库存预警上限,并在条件满足时生成提示信息。
首先,用户声明了两个变量@DACTUALWEIGHT和@DHIGHWEIGHT,然后使用两个公共表表达式(CTE)SalesData和StockData来分别获取销售数据和库存数据。接着,通过JOIN操作将这两个CTE与WM_SafeStockDts表连接,计算@DACTUALWEIGHT和@DHIGHWEIGHT的值。最后,有一个条件判断,如果实际重量加上某个@DLENGTHSUM超过高权重,则拼接提示信息。
用户希望优化这段代码。我需要考虑优化的方向,可能的点包括:提高查询性能、代码可读性、变量命名、逻辑简化等。
首先检查CTE部分。SalesData和StockData都从SM_SaleOrder和SM_SaleOrderDts表获取数据,但SalesData的条件里有A.DSYSID = B.DSYSID,而StockData中INNER JOIN SM_SaleOrderDts B ON ... AND B.DSYSID=1112194。注意到两个CTE都关联到同一个DSYSID=1112194,这可能是在处理特定订单。但是,在SalesData的WHERE子句中,A.DSYSID=1112194没有被显式写出,这可能是个问题?或者原代码中的JOIN条件是A.DSYSID = B.DSYSID,而B.DSYSID在SalesData的WHERE中被过滤了吗?
仔细看SalesData的FROM子句:A INNER JOIN B ON A.DSYSID = B.DSYSID。然后WHERE条件包括A.DISSTORE=1 OR DPTNCODE='M-SXYS-00623',以及A.DSTATERUN IN(12,13)等,但这里可能没有限制A.DSYSID,导致可能关联到多个订单,而用户可能只需要DSYSID=1112194的记录。这可能是个错误,因为StockData中的B.DSYSID=1112194,而SalesData中没有这个条件,导致SalesData可能包含其他订单的数据,这不符合预期。这可能是需要优化的地方,应该将SalesData中的A.DSYSID=1112194加入WHERE条件,否则会关联到所有符合条件的订单,而StockData只关联到特定订单,导致数据不一致。
例如,原SalesData的WHERE子句中没有A.DSYSID=1112194,而StockData中的B.DSYSID=1112194,这可能使得两个CTE的数据范围不一致,导致后续的JOIN结果错误。所以这是一个潜在的问题,需要修正。
接下来,检查JOIN条件。在SalesData中,关联的是A.DSYSID = B.DSYSID,这可能意味着每个SaleOrder对应多个SaleOrderDts,但如果没有过滤A.DSYSID,可能SalesData会包含多个订单的数据。但用户可能只处理特定订单(DSYSID=1112194),所以应该在SalesData的WHERE子句中添加A.DSYSID=1112194,或者在JOIN时就限定。例如,原代码中的WHERE子句是否应该包括A.DSYSID=1112194?因为后续的StockData中的B.DSYSID=1112194,所以可能SalesData也应该限制同一订单。
这是关键点,因为如果SalesData没有过滤DSYSID=1112194,那么它会汇总所有符合条件的订单的数据,而StockData只关联到该特定订单,这可能导致数据汇总错误,进而影响@DACTUALWEIGHT和@DHIGHWEIGHT的计算。所以这一步需要修正,确保SalesData只处理DSYSID=1112194的订单。
接下来,查看StockData的JOIN条件:A INNER JOIN SM_SaleOrderDts B ON A.DITEMCODE=B.DITEMCODE AND A.DCOLORCODE=B.DCOLORCODE AND A.DCOLORNAME=B.DCOLORNAME AND B.DSYSID=1112194。这里B.DSYSID=1112194,所以StockData只关联到该订单的Dts记录。但SalesData可能没有这个限制,导致两个CTE的数据范围不同,进而影响后续的INNER JOIN和LEFT JOIN。
因此,优化点一:在SalesData的WHERE子句中添加A.DSYSID=1112194,以确保只处理该订单的数据。这可能提高性能,并确保数据一致性。
接下来,检查变量声明部分。用户声明了@DACTUALWEIGHT和@DHIGHWEIGHT,然后在SELECT语句中赋值。但后续的IF条件中使用了@DLENGTHSUM,这个变量在代码中没有声明,这可能是个错误,或者用户可能在代码的其他部分声明了它。但根据提供的代码片段,@DLENGTHSUM未定义,这会导致错误。需要确认是否变量名有误,或者是否是拼写错误。例如,是否应该是SalesData中的SUM(B.DLENGTH) AS DLENGTH,而@DLENGTHSUM应该是来自其他地方的变量?或者是否应该用SalesData中的DLENGTH总和?
在最后的SELECT语句中,@DACTUALWEIGHT被赋值为SUM(C.DLENGTH),而C来自StockData,即库存数据的总长度。而@DHIGHWEIGHT是SUM(A.DHIGHWEIGHT),来自WM_SafeStockDts表。然后IF条件判断@DACTUALWEIGHT + @DLENGTHSUM > @DHIGHWEIGHT。这里的@DLENGTHSUM应该是当前订单的总长度,即SalesData中的SUM(B.DLENGTH)。但原代码中,SalesData的DLENGTH被汇总了,但可能未被保存到变量中。因此,在后续的IF语句中,用户可能错误地使用了@DLENGTHSUM,而实际上应该使用SalesData中的DLENGTH总和。
例如,原代码中的SalesData汇总了B.DITEMCODE等的DLENGTH总和,但在最后的SELECT中,@DACTUALWEIGHT是来自StockData的C.DLENGTH总和,而@DHIGHWEIGHT是来自WM_SafeStockDts的DHIGHWEIGHT总和。然后IF条件中的@DLENGTHSUM可能应该是SalesData中的DLENGTH总和,即SUM(B.DLENGTH)。但原代码中并没有将这个值赋给变量,导致@DLENGTHSUM未定义。因此,这可能是一个逻辑错误,需要修正。
所以优化点二:计算SalesData中的总DLENGTH,并将其赋值给一个变量(例如@DLENGTHSUM),以便在IF条件中使用。否则,当前代码中的@DLENGTHSUM是未定义的,会导致错误。
现在,考虑如何调整代码。在最后的SELECT语句中,除了计算@DACTUALWEIGHT和@DHIGHWEIGHT,还应该计算SalesData中的总DLENGTH,并赋值给@DLENGTHSUM变量。例如:
SELECT
@DACTUALWEIGHT = SUM(C.DLENGTH),
@DHIGHWEIGHT = SUM(A.DHIGHWEIGHT),
@DLENGTHSUM = SUM(B.DLENGTH)
FROM ...
这样,在后续的IF条件中就可以正确使用@DLENGTHSUM。原代码中的@DLENGTHSUM可能是用户遗漏定义的变量,这会导致运行时错误,必须修复。
接下来,检查字符串拼接部分。用户使用SET @DAUDITPROMTS += ...,其中@DAUDITPROMTS可能是一个存储提示信息的变量。在拼接时,使用了CAST将数值转换为VARCHAR(20),但DEC(18,3)类型的变量可能有较多小数位,直接转换可能显示多余的小数,例如123.456。用户是否需要保留三位小数,或者转换为更合适的格式?例如,使用CAST(AS DECIMAL(18,0))先取整,或者使用FORMAT函数(如果可用)来格式化数字。
此外,字符串拼接时使用了多个加号,可能导致效率问题,但在此处影响不大。另外,CHAR(13)+CHAR(10)可以用CHAR(13) + CHAR(10) 或者直接使用CHAR(13) + CHAR(10),不过更简洁的方式是使用换行符常量,比如 + '\r\n',但SQL Server中需要用单引号,并且可能需要用NCHAR(13) + NCHAR(10)或者直接拼接。
优化点三:确保数值转换的格式正确,可能使用更合适的CAST或CONVERT,例如指定小数位数,或者去除多余的小数位。例如,CAST(CAST(@DLENGTHSUM AS DECIMAL(18,0)) AS VARCHAR(20)),以去掉小数部分,如果不需要的话。
此外,代码中的JOIN操作可能可以优化。例如,在WM_SafeStockDts A INNER JOIN SalesData B ON ...,然后LEFT JOIN StockData C ON ...。这里是否可以使用更有效的JOIN方式?例如,检查索引是否存在,或者是否存在不必要的JOIN条件。
另外,检查WHERE条件中的DWHTYPE=4和DWHCODE IN ('C03','C06'),以及DSSALEOPID='综合部'是否有合适的索引,以提高StockData的查询效率。
优化点四:添加必要的索引,例如在WM_Stock表的DITEMCODE, DCOLORCODE, DCOLORCODE上,以及WHERE条件中的字段。
代码可读性方面,可以格式化SQL代码,使其更易读。例如,统一缩进,使用别名等。
此外,变量命名方面,@DACTUALWEIGHT和@DHIGHWEIGHT可能不够明确,但可能符合用户的命名规范,所以暂不修改。
最后,检查是否存在重复计算。例如,SalesData和StockData都关联到SM_SaleOrderDts B,而B.DSYSID=1112194。确保这些关联条件正确,避免重复或遗漏。
总结优化步骤:
1. 在SalesData的WHERE子句中添加A.DSYSID=1112194,确保只处理当前订单的数据。
2. 在最后的SELECT语句中计算SalesData的总DLENGTH并赋值给@DLENGTHSUM变量,修复未定义的变量问题。
3. 在CAST转换时处理小数位数,确保提示信息中的数值格式正确。
4. 检查并优化JOIN条件和索引,提高查询性能。
5. 格式化代码,提高可读性。
6. 修正可能的逻辑错误,例如数据范围不一致。
现在,根据以上分析,编写优化后的代码,并解释每个优化点。</think>以下是对该SQL代码的优化分析和改进建议:
### 一、主要问题分析
1. **数据范围不一致**
SalesData未限定DSYSID=1112194,导致与StockData数据范围不同
2. **未定义变量**
`@DLENGTHSUM` 未赋值直接使用,会导致运行时错误
3. **小数显示问题**
DEC(18,3)类型直接转VARCHAR会产生三位小数(如123.456)
4. **代码可读性**
嵌套查询和连接条件可读性较差
### 二、优化后的代码
```sql
DECLARE
@DACTUALWEIGHT DEC(18,3),
@DHIGHWEIGHT DEC(18,3),
@DLENGTHSUM DEC(18,3), -- 新增变量
@DAUDITPROMTS VARCHAR(MAX) = '';
WITH SalesData AS (
SELECT
B.DITEMCODE,
B.DCOLORCODE,
B.DCOLORNAME,
SUM(B.DLENGTH) AS DLENGTH
FROM SM_SaleOrder A
INNER JOIN SM_SaleOrderDts B
ON A.DSYSID = B.DSYSID
WHERE A.DSYSID = 1112194 -- 新增限制条件
AND (A.DISSTORE = 1 OR DPTNCODE = 'M-SXYS-00623')
AND A.DSTATERUN IN (12,13)
AND A.DMODULENO = '210101'
GROUP BY B.DITEMCODE, B.DCOLORCODE, B.DCOLORNAME
),
StockData AS (
SELECT
A.DITEMCODE,
A.DCOLORCODE,
A.DCOLORNAME,
SUM(A.DLENGTH) AS DLENGTH
FROM WM_Stock A
INNER JOIN SM_SaleOrderDts B
ON A.DITEMCODE = B.DITEMCODE
AND A.DCOLORCODE = B.DCOLORCODE
AND A.DCOLORNAME = B.DCOLORNAME
WHERE B.DSYSID = 1112194
AND DWHTYPE = 4
AND DWHCODE IN ('C03','C06')
AND DSSALEOPID = '综合部'
GROUP BY A.DITEMCODE, A.DCOLORCODE, A.DCOLORNAME
)
SELECT
@DACTUALWEIGHT = SUM(C.DLENGTH),
@DHIGHWEIGHT = SUM(A.DHIGHWEIGHT),
@DLENGTHSUM = SUM(B.DLENGTH) -- 新增赋值
FROM WM_SafeStockDts A
INNER JOIN SalesData B
ON A.DITEMCODE = B.DITEMCODE
AND A.DCOLORCODE = B.DCOLORCODE
AND A.DCOLORNAME = B.DCOLORNAME
LEFT JOIN StockData C
ON A.DITEMCODE = C.DITEMCODE
AND A.DCOLORCODE = C.DCOLORCODE
AND A.DCOLORNAME = C.DCOLORNAME;
IF @DACTUALWEIGHT + @DLENGTHSUM > @DHIGHWEIGHT
BEGIN
SET @DAUDITPROMTS += CONCAT(
'l、该订单的订单量(',
CAST(CAST(@DLENGTHSUM AS DECIMAL(18,0)) AS VARCHAR(20)), -- 去除小数
'kg)加上当前库存(',
CAST(CAST(@DACTUALWEIGHT AS DECIMAL(18,0)) AS VARCHAR(20)),
'kg),将会超出库存预警上限(',
CAST(CAST(@DHIGHWEIGHT AS DECIMAL(18,0)) AS VARCHAR(20)),
'kg)', CHAR(13), CHAR(10)
);
END
```
### 三、优化点说明
1. **数据一致性**
在SalesData的WHERE条件中增加`A.DSYSID = 1112194`,确保与StockData处理相同订单
2. **变量定义**
新增`@DLENGTHSUM`变量并赋值`SUM(B.DLENGTH)`,解决未定义变量问题
3. **数值格式化**
通过双重CAST先转DECIMAL(18,0)去除小数,再转VARCHAR保证显示整数
4. **性能优化**
- 为关键字段添加索引:
```sql
CREATE INDEX IDX_SaleOrder_DSYSID ON SM_SaleOrder(DSYSID)
CREATE INDEX IDX_Stock_Composite ON WM_Stock(DITEMCODE, DCOLORCODE, DCOLORNAME)
```
- 使用CONCAT()替代字符串拼接,提高可读性和空值安全性
5. **代码可读性**
- 统一缩进格式
- 显式标注新增内容
- 拆分长代码为多行
### 四、执行建议
1. 在测试环境验证数据一致性
2. 检查WM_SafeStockDts与SalesData的关联关系
3. 监控库存预警逻辑的实际业务效果
阅读全文
相关推荐













