sql - 如何在查询中多次重复使用复杂的公式
问题描述
我有几个半复杂的公式查询。我删除了很多额外的内容,并将其归结为与我的问题相关的内容。
DECLARE @Company AS NVARCHAR(8) = 'Acme'
, @Plant AS VARCHAR(20) = 'Albuquerque'
, @Warehouse AS NVARCHAR(8) = 'TNT-WH1'
, @DaysAhead AS INT = 10
, @FulfillmentThreshold AS INT = 90;
SELECT
@Company AS 'Company'
, orel.SellingReqQty
, orel.OurJobShippedQty + orel.OurStockShippedQty AS 'ShippedQty'
, orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty) AS 'ReqQtyRemaining'
, CASE
WHEN ((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ (orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)) * 100)
>= 100 THEN '100'
ELSE
((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ (orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)) * 100)
END
AS 'PercentAvailToFulfill'
FROM
dbo.OrderRel AS orel WITH (NOLOCK)
INNER JOIN erp.PartWhse AS pw WITH (NOLOCK)
ON (pw.Company = orel.Company AND
pw.PartNum = orel.PartNum AND
pw.WarehouseCode = @Warehouse)
WHERE
orel.Company = @Company
AND orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty) > 0 -- ReqQtyRemaining
AND (orel.ReqDate <= DATEADD(DAY, @DaysAhead, GETDATE())
OR
orel.RushPart_c = 1 )
AND ((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ (orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)) * 100)
> @FulfillmentThreshold
AND (orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)) > (pw.AllocatedQty + pw.ReservedQty)
如您所见,表示剩余数量的这段代码重复了很多次,但对于返回的每条记录都需要计算:
orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)
我正在寻找一种通过将其更改为单个变量来使其更具可读性的方法。是否可以将其设置为为每一行计算的变量,以便我可以将其称为@ReqQtyRemaining?
解决方案
在您的情况下,如果所有这些列都在同一个表中,您可以使用COMPUTED
column.
因此,您只需修改表结构以添加新的计算列。
ALTER TABLE dbo.OrderRel ADD ReqQtyRemaining AS (SellingReqQty - OurJobShippedQty + OurStockShippedQty)
一旦你创建了一个计算列,这个列作为一个名字说将总是自动更新,它可以在查询中作为所有其他列使用,你不能手动更新这个列。
然后你不需要在查询中进行计算,而且你也可以在这个列上放置一个索引。
如果您无法更改表结构,您可以尝试使用CTE (Common Table Expressions)
. 但是,您不会看到任何具体的性能改进,您只会提高相同代码的可读性和可重用性。因此,您的查询应如下所示:
DECLARE @Company AS NVARCHAR(8) = 'Acme'
, @Plant AS VARCHAR(20) = 'Albuquerque'
, @Warehouse AS NVARCHAR(8) = 'TNT-WH1'
, @DaysAhead AS INT = 10
, @FulfillmentThreshold AS INT = 90;
;WITH OrderRelWithComputedCTE AS
(
SELECT *, (SellingReqQty - OurJobShippedQty + OurStockShippedQty) ReqQtyRemaining
FROM dbo.OrderRel WITH (NOLOCK)
)
SELECT
@Company AS 'Company'
, orel.SellingReqQty
, orel.OurJobShippedQty + orel.OurStockShippedQty AS 'ShippedQty'
, orel.ReqQtyRemaining
, CASE
WHEN ((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ orel.ReqQtyRemaining * 100)
>= 100 THEN '100'
ELSE
((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ orel.ReqQtyRemaining * 100)
END
AS 'PercentAvailToFulfill'
FROM
OrderRelWithComputedCTE AS orel
INNER JOIN erp.PartWhse AS pw WITH (NOLOCK)
ON (pw.Company = orel.Company AND
pw.PartNum = orel.PartNum AND
pw.WarehouseCode = @Warehouse)
WHERE
orel.Company = @Company
AND orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty) > 0 -- ReqQtyRemaining
AND (orel.ReqDate <= DATEADD(DAY, @DaysAhead, GETDATE())
OR
orel.RushPart_c = 1 )
AND ((pw.OnHandQty - (pw.AllocatedQty + pw.ReservedQty))
/ orel.ReqQtyRemaining * 100)
> @FulfillmentThreshold
AND orel.ReqQtyRemaining > (pw.AllocatedQty + pw.ReservedQty)
注意CTE
SELECT 语句顶部和这一行的命令:
FROM OrderRelWithComputedCTE AS orel
推荐阅读
- sql-server - SQL数据库中的数据库下可以创建表吗?
- google-apps-script - 使用谷歌脚本将谷歌驱动器视频插入谷歌幻灯片
- javascript - axios拦截器拦截所有axios请求
- asp.net - 如何在 Identity Server 4 保护的 webapi 中访问自定义声明?
- java - 没有虚拟方法 verifyPhoneNumber,致命异常:main
- mql4 - 为什么这个字符串函数不更新?MQL4
- java - Java 中的刽子手游戏并没有脱离循环
- python - 如何修复在赋值前引用的第 6 行封闭范围中定义的“局部变量”prev_time”错误
- html - Sendgrid 暗模式与两个徽标的兼容性
- python - 从python3中的div中获取特定文本