Sql 使用范围和有限兼容性进行小计
在SQLServer2008R2上,我试图创建一个存储过程,根据用户输入的商品范围为用户提供商品小计。我将感谢任何帮助 然而,我遇到了一个问题,查询显示了所有正在计算的商品,因此用户以最终将超过其输入范围的值结束。我将在底部包括一些示例数据以及我尝试过的内容 下面是一个示例,为了在本示例中更清晰,我在其中删除了一些列: 如您所知,对于2000到10000之间的范围,商品998-32的小计将超过10000,但仍会显示,因为每个采购订单号单独小于10000 以下是一些示例数据:Sql 使用范围和有限兼容性进行小计,sql,stored-procedures,sql-server-2008-r2,Sql,Stored Procedures,Sql Server 2008 R2,在SQLServer2008R2上,我试图创建一个存储过程,根据用户输入的商品范围为用户提供商品小计。我将感谢任何帮助 然而,我遇到了一个问题,查询显示了所有正在计算的商品,因此用户以最终将超过其输入范围的值结束。我将在底部包括一些示例数据以及我尝试过的内容 下面是一个示例,为了在本示例中更清晰,我在其中删除了一些列: 如您所知,对于2000到10000之间的范围,商品998-32的小计将超过10000,但仍会显示,因为每个采购订单号单独小于10000 以下是一些示例数据: DROP TABLE
DROP TABLE ##mytable;
CREATE TABLE ##mytable(
Commodity VARCHAR(15) NOT NULL
,PO_NO INTEGER NOT NULL
,LINE_NO INTEGER NOT NULL
,PO_Line_Description VARCHAR(82)
,Commodity_Description VARCHAR(60) NOT NULL
,Fiscal_Year INTEGER NOT NULL
,Vendor_ID INTEGER NOT NULL
,Vendor_Name VARCHAR(20) NOT NULL
,QUANTITY INTEGER NOT NULL
,UNIT_COST NUMERIC(7,2) NOT NULL
,Line_Amount NUMERIC(7,2) NOT NULL
);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-18',1448923,1,'Face Scholastic book order attached.','Sale of Surplus and Obsolete Books',2015,47650,'SCHOLASTIC INC',1,9999.8,9999.8);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1416311,2,'First 12 months maintenance agreement to be billed quarterly at .0039 per b/w copy','Sale of Surplus and Obsolete Copy Machines',2015,341479,'RICOH USA, INC',1,5148,5148);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1424377,1,NULL,'Sale of Surplus and Obsolete Copy Machines',2015,300590,'KONICA MINOLTA/ CIT',1,2894.58,2894.58);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1404031,1,'1st (12) months of (36) month Lease payment for (1) MPC4503 copier.','Sale of Surplus and Obsolete Copy Machines',2015,341479,'RICOH USA, INC',1,2050.68,2050.68);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-75',1401552,1,'Blanket order for 50 teachers - each teacher not to exceed $100.00.','Sale of Surplus and Obsolete Paper and Paper Products',2015,27536,'KNOWLEDGE TREE',1,5000,5000);
INSERT INTO ##mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-78',1521390,1,'PL02286>PRESSURE PLUMBER INSTANT DRAIN OPENER 24 SHOT CARTRIDGE','Sale of Surplus and Obsolete Plumbing Equipment and Supplies',2015,402985,'TECH MECH SUPPLY LLC',480,8,3840);
我曾尝试使用前面没有边界的按[]顺序按[]行划分的SUM OVER分区,但显然,带行的OVER子句是在SQL Server 2012中引入的,不适用于2008 R2
我也尝试过使用GROUP BY ROLLUP,但是我收到一条消息,说在当前的兼容模式下不允许使用多维数据集和ROLLUP分组结构。仅允许在100模式或更高模式下使用。当我问我们的DBA时,他说我们不能从90模式转移到100模式,因为很多东西都会崩溃
因此,现在我陷入了下面的查询,它有前面提到的问题,即提供我想要的数据的问题,以及最终将超过我指定范围的数据小计的问题
另外,我还注意到,如果商品的采购订单号在我选择的范围内,但采购订单号的成本也在我选择的范围之外,则此查询将给出所选范围内的采购订单号,这是非常误导我的,因为如果全部计算,它仍然是一种超出所选范围的商品。它们根本不应该与真正在我选择范围内的商品一起列入结果
ALTER PROCEDURE [dbo].[POreport] (
@Param1 INT
,@Param2 INT
,@Param3 INT
)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT ROW_NUMBER() OVER (
ORDER BY T.Product_ID
,T.PO_NO
,T.LINE_NO
) AS [RowID]
,ISNULL(T.PRODUCT_ID, 'NULL') AS [Commodity]
,ISNULL(T.PO_NO, 'NULL') AS [PO NO]
,ISNULL(T.LINE_NO, 'NULL') AS [LINE NO]
,QUOTENAME(T.DESCRIPTION, '"') AS [PO Line Description]
,QUOTENAME(C.DESCRIPTION, '"') AS [Commodity Description]
,ISNULL(T.FY, 'NULL') AS [Fiscal Year]
,PH.Vendor_ID AS [Vendor ID]
,QUOTENAME(V.Vendor_Name, '"') AS [Vendor Name]
,T.QUANTITY
,T.UNIT_COST
,T.QUANTITY * T.UNIT_COST AS [Line Amount]
,(
SELECT CAST(0.00 AS NUMERIC(10, 2))
) AS Sub_Total_Cost
INTO ##TmpPOReport
FROM dbo.DBVW_FI_REQ_PO_ITEMS T
INNER JOIN dbo.FI_VENDOR FV ON T.INST_ID = FV.INST_ID
INNER JOIN dbo.FI_REQ_PO_HEADER PH ON T.PO_NO = PH.PO_NO
INNER JOIN dbo.FI_VENDOR V ON PH.VENDOR_ID = V.VENDOR_ID
INNER JOIN dbo.FI_COMMODITY C ON T.PRODUCT_ID = C.FI_COMMODITY_CODE
WHERE T.INST_ID = 'SC00'
AND T.FY = @Param1
AND V.VENDOR_TYPE = 'V'
AND T.PO_NO IS NOT NULL
AND (
T.PRODUCT_ID <> ''
AND T.PRODUCT_ID IS NOT NULL
)
AND T.QUANTITY * T.UNIT_COST BETWEEN @Param2
AND @Param3
GROUP BY T.PRODUCT_ID
,T.PO_NO
,T.LINE_NO
,T.DESCRIPTION
,C.DESCRIPTION
,T.FY
,PH.Vendor_ID
,V.Vendor_Name
,T.QUANTITY
,T.UNIT_COST
,PH.Created_Date
ORDER BY Commodity
DECLARE @PID VARCHAR(15) = 00
,@QUANTITY INT
,@UNIT_COST NUMERIC(10, 2)
,@PrevID VARCHAR(15)
,@RowID BIGINT
,@PrevRowID BIGINT
,@RowAmount NUMERIC(10, 2)
,@SubTotal NUMERIC(10, 2) = 0.00
SET NUMERIC_ROUNDABORT OFF;
WHILE EXISTS (
SELECT TOP 1 *
FROM ##TmpPOReport
WHERE Sub_Total_Cost = 0.00
)
BEGIN
SET @RowAmount = (
SELECT TOP 1 (QUANTITY * UNIT_COST)
FROM ##TmpPOReport
WHERE Sub_Total_Cost = 0.00
)
SELECT TOP 1 @PID = Commodity
,@RowID = RowID
FROM ##TmpPOReport
WHERE Sub_Total_Cost = 0.00
IF (@PID = @PrevID)
AND (@RowID <> @PrevRowID)
BEGIN
SET @SubTotal += @RowAmount;
UPDATE T
SET Sub_Total_Cost = @SubTotal
FROM ##TmpPOReport T
WHERE T.Commodity = @PID
AND RowID = @RowID
SET @PrevID = @PID;
SET @PrevRowID = @RowID
END
ELSE
BEGIN
SET @SubTotal = @RowAmount;
UPDATE T
SET Sub_Total_Cost = @SubTotal
FROM ##TmpPOReport T
WHERE T.Commodity = @PID
AND RowID = @RowID
SET @PrevID = @PID;
SET @PrevRowID = @RowID
END
END
SET NUMERIC_ROUNDABORT ON;
SELECT *
FROM ##TmpPOReport
WHERE [Line Amount] BETWEEN @Param2
AND @Param3
DROP TABLE ##TmpPOReport
END
谢谢 如果不清楚,很抱歉。如果要在行上复制总和,则需要使用下面的CTE或类似子查询。这不是一个优化的查询,但它将为您提供商品的运行总和。它使用分区排名来获取商品中每个PO的实例或行号
DECLARE @mytable TABLE(
Commodity VARCHAR(15) NOT NULL
,PO_NO INTEGER NOT NULL
,LINE_NO INTEGER NOT NULL
,PO_Line_Description VARCHAR(82)
,Commodity_Description VARCHAR(60) NOT NULL
,Fiscal_Year INTEGER NOT NULL
,Vendor_ID INTEGER NOT NULL
,Vendor_Name VARCHAR(20) NOT NULL
,QUANTITY INTEGER NOT NULL
,UNIT_COST NUMERIC(7,2) NOT NULL
,Line_Amount NUMERIC(7,2) NOT NULL
);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-18',1448923,1,'Face Scholastic book order attached.','Sale of Surplus and Obsolete Books',2015,47650,'SCHOLASTIC INC',1,9999.8,9999.8);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1416311,2,'First 12 months maintenance agreement to be billed quarterly at .0039 per b/w copy','Sale of Surplus and Obsolete Copy Machines',2015,341479,'RICOH USA, INC',1,5148,5148);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1424377,1,NULL,'Sale of Surplus and Obsolete Copy Machines',2015,300590,'KONICA MINOLTA/ CIT',1,2894.58,2894.58);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-32',1404031,1,'1st (12) months of (36) month Lease payment for (1) MPC4503 copier.','Sale of Surplus and Obsolete Copy Machines',2015,341479,'RICOH USA, INC',1,2050.68,2050.68);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-75',1401552,1,'Blanket order for 50 teachers - each teacher not to exceed $100.00.','Sale of Surplus and Obsolete Paper and Paper Products',2015,27536,'KNOWLEDGE TREE',1,5000,5000);
INSERT INTO @mytable(Commodity,PO_NO,LINE_NO,PO_Line_Description,Commodity_Description,Fiscal_Year,Vendor_ID,Vendor_Name,QUANTITY,UNIT_COST,Line_Amount) VALUES ('998-78',1521390,1,'PL02286>PRESSURE PLUMBER INSTANT DRAIN OPENER 24 SHOT CARTRIDGE','Sale of Surplus and Obsolete Plumbing Equipment and Supplies',2015,402985,'TECH MECH SUPPLY LLC',480,8,3840);
DECLARE @FiscalYear INT
DECLARE @LowTotalCost INT
DECLARE @HighTotalCost INT
SET @FiscalYear=2015
SET @LowTotalCost=1000
SET @HighTotalCost=10000
SELECT
*
FROM
(
SELECT Commodity,PO_NO,QUANTITY,UNIT_COST,Line_Amount,
RunningTotal=
(
SELECT SUM(TotalCost) FROM
(
SELECT Commodity,TotalCost =(MT.QUANTITY * MT.UNIT_COST),
Instance=RANK()OVER(PARTITION BY Commodity ORDER BY Commodity,PO_NO DESC)
FROM
@mytable MT
WHERE
(MT.QUANTITY * MT.UNIT_COST) BETWEEN @LowTotalCost AND @HighTotalCost
AND
(MT.Fiscal_Year=@FiscalYear)
)AS Y
WHERE
(Y.Commodity=X.Commodity) AND(Y.Instance<=X.Instance)
)
FROM
(
SELECT Commodity,PO_NO,QUANTITY,UNIT_COST,Line_Amount,
TotalCost = (MT.QUANTITY * MT.UNIT_COST),
Instance=RANK()OVER(PARTITION BY Commodity ORDER BY Commodity,PO_NO DESC)
FROM
@mytable MT
WHERE
--IS FILTER HERE -->(MT.QUANTITY * MT.UNIT_COST) BETWEEN @LowTotalCost AND @HighTotalCost
--AND
(MT.Fiscal_Year=@FiscalYear)
)AS X
)AS Z
WHERE
(Commodity IN
(
SELECT Commodity FROM
(
SELECT
Commodity,
Total=SUM(QUANTITY * UNIT_COST)
FROM
@mytable mt2
WHERE
mt2.Fiscal_Year=@FiscalYear
GROUP BY
Commodity
)AS A
WHERE
A.Total BETWEEN @LowTotalCost AND @HighTotalCost
)
)
SELECT
*
FROM
@mytable MT
从我所看到的使用你的结果来看,它给了我和上面一样的东西:它遇到了同样的误导问题。如果我为商品选择一个范围,它将给我不完整的运行总数。例如,当我选择1000到10000之间的商品时,商品998-32将显示8042.58和2894.58,而998-32实际上是10093.26大于10000。是否有一种方法可以添加一个列,该列是每种商品的最高运行总量,以便我可以从中选择我的范围?谢谢。我在中添加了关于商品的最终WHERE条款,以支持您评论中的问题。然而,在这一点上,我将转换并使用CTE,因为它将更具可读性。然而,我确实注意到,如果商品数量相同,而不考虑会计年度,它就添加了商品小计。例如,对于商品035-10,无论2014年、2015年或2016年作为财政年度,它都会将所有运行总计相加。是否有办法将运行总额与财年和商品分开,以便在2014年和2015年分别计算035-10和035-10的运行总额,等等?或者有办法将运行总额与财年和商品分组?