Sql 如何在查询中多次重复使用复杂公式

Sql 如何在查询中多次重复使用复杂公式,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个查询,有几个半复杂的公式。我删除了很多多余的部分,并将其归结为与我的问题相关的内容 DECLARE @Company AS NVARCHAR(8) = 'Acme' , @Plant AS VARCHAR(20) = 'Albuquerque' , @Warehouse AS NVARCHAR(8) = 'TNT-WH1'

我有一个查询,有几个半复杂的公式。我删除了很多多余的部分,并将其归结为与我的问题相关的内容

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)

我正在寻找一种方法,通过将其更改为单个变量来提高可读性。是否可以将其设置为一个为每行计算的变量,以便我可以将其称为@ReqTyremaining?

在您的情况下,如果所有这些列都在同一个表中,您可以使用COMPUTED column

所以,您只需要修改表结构以添加新的计算列

更改表dbo.OrderRel将ReqtyRemaining添加为SellingReqty-OurJobShippedQty+OurStockShippedQty 一旦您创建了一个计算列,该列作为所说的名称将始终自动更新,并且可以在查询中与所有其他列一样使用,您就不能手动更新该列

这样,您就不需要在查询中进行计算,而且还可以在该列上添加索引

更多信息请点击此处:

如果无法更改表结构,可以尝试使用CTE公用表表达式。但是,您不会看到任何特定的性能改进,您只会改进同一代码的可读性和可重用性。那么,您的查询应该如下所示:

声明@Company为NVARCHAR8='Acme' ,@Plant AS VARCHAR20='Albuquerque' ,@仓库名称为NVARCHAR8='TNT-WH1' ,@dayshead作为INT=10 ,@FulfillmentThreshold为INT=90; ;使用OrderRelWithComputedCTE作为 选择*,SellingReqtQTY-OurJobShippedQty+OurStockShippedQty ReqtyRemaining 从dbo.OrderRel到NOLOCK 选择 @公司名称为“公司” ,或销售需求数量 ,orel.OurJobShippedQty+orel.OurStockShippedQty为'ShippedQty' ,orel.ReqtyRemaining 案例 当pw.OnHandQty-pw.AllocatedQty+pw.ReservedQty时 /orel.ReqtyRemaining*100 >=100然后是“100” 其他的 pw.OnHandQty-pw.AllocatedQty+pw.ReservedQty /orel.ReqtyRemaining*100 终止 作为“完成百分比” 从…起 OrderRelWithComputedCTE AS orel 内部连接erp.PARTHSE作为pw与NOLOCK ON pw.Company=欧莱尔公司和 pw.PartNum=orel.PartNum和 pw.WarehouseCode=@Warehouse 哪里 orel.Company=@Company 和orel.SellingReqQty-orel.OurJobShippedQty+orel.OurStockShippedQty>0-ReqTyremaining 以及orel.ReqDate@FulfillmentThreshold 和orel.ReqtyRemaining>pw.AllocatedQty+pw.ReservedQty 请注意SELECT语句顶部的CTE命令以及这一行:

从OrderRelWithComputedCTE作为orel
不能在返回数据集的语句中设置变量,每行设置一个变量没有意义;所有变量都是标量值,因此它们只能保存标量值。这听起来像是一个错误。如果要计算运行总数,请使用窗口聚合函数。还有,你需要那些NOLOCK提示吗?您知道它们很容易导致返回的数据出错,对吗?另请注意,建议不要对别名使用单引号。单引号用于文字字符串,读起来会很混乱。如果必须对别名进行分隔标识,请使用T-SQL分隔标识符括号[]或ISO分隔标识符双引号;否则不要引用它们。似乎您只是想避免重复表达orel.SellingReqty-orel.OurJobShippedQty+orel.OurStockShippedQty。也许使用crossapply对其进行一次评估可以根据您的喜好简化查询。看看。@Larnu这句话很有趣,我不知道。我们在PHP中构造这些查询字符串,所以我们通常对外部字符串使用双引号,对内部字符串使用单引号。我们有一个喜欢别名中空格的开发人员$query=选择t.column作为“我的别名”@使用带有NOLOCK提示的Larnu是因为我们可以说是这个DB上的来宾。作为来宾,我们不想干扰数据库的任何正常操作,即使我们得到的数据有点不正确,也不会被用来提供生死攸关的信息。我认为,在实际生产用户进行交易时,作为客人,不锁定任何表是很重要的。这是一个好主意。不幸的是,在我们的例子中,我们根本无法更改数据库,但这可能会在将来帮助其他人使用相同的用例。好主意@如果你不能改变桌子的结构,我已经更新了我的答案。这很有魅力!对你的两个想法来说都是非常好的信息。谢谢。我希望这可以帮助其他人简化SQL脚本中丑陋公式的重用。
orel.SellingReqQty - (orel.OurJobShippedQty + orel.OurStockShippedQty)