我正在尝试选择前n行,其中列的总和小于或等于我作为变量传入的数字。
TableX的:
Col1 Col2
1 10
2 10
3 5
4 20
所以基本上我正在尝试做这样的事情:
SELECT * FROM TableX WHERE SUM(Col2) <= 25
我期待结果:
Col1 Col2
1 10
2 10
3 5
答案 0 :(得分:3)
您正在寻找HAVING条款。
不幸的是,我此时无法访问sql server来测试一个完整的解决方案,但是...在mysql中这似乎完全符合你的要求,如果我有T-SQL也应该这样做我没弄错。
SELECT A.Col1, A.Col2, SUM(B.Col2) AS CumulativeCol2
FROM TableX A
INNER JOIN TableX B ON B.Col1 <= A.Col1
GROUP BY A.Col1
HAVING SUM(B.Col2) <= 25
返回:
Col1 Col2 CumulativeCol2
1 10 10
2 10 20
3 5 25
答案 1 :(得分:2)
declare @table as table(Col1 int, Col2 int)
insert into @table values (1, 10)
insert into @table values (2, 10)
insert into @table values (3, 5)
insert into @table values (4, 20)
;with TableWithIndex(Row, Col1, Col2)
as
(
select row_number() over(order by Col1) Row, Col1, Col2
from @table
),
ColTable(Row, Col1, Col2, Col2Sum)
as (
select Row, Col1, Col2, Col2 Col2Sum
from TableWithIndex
where Row = 1 and Col2 <= 25
union all
select ti.Row, ti.Col1, ti.Col2, ti.Col2 + Col2Sum
from TableWithIndex ti
inner join ColTable ct on ct.Row + 1 = ti.Row
where ti.Col2 + Col2Sum <= 25
)
select Col1, Col2
from ColTable
option (maxrecursion 0)
答案 2 :(得分:1)
这是您需要的(包括概念证明):
declare @t table(Col1 int, Col2 int)
insert into @t values
(1, 10),
(2, 10),
(3, 5),
(4, 20),
(5, 3)
select * from
(
select t1.Col1, t1.Col2, SUM(t2.Col2) as runningtotal
from @t t1
inner join @t t2 on t1.Col1 >= t2.Col1
group by t1.Col1, t1.Col2
) ss
where runningtotal <= 25
答案 3 :(得分:0)
修改:请勿将TestDataID identity(1,1)
列中的值与RowNumber
值混淆。这些值之间没有联系。
此解决方案使用递归CTE:
CREATE TABLE TestData
(
TestDataID INT IDENTITY(2,2) PRIMARY KEY
,ProductID INT NOT NULL
,SalesQty INT NOT NULL
);
INSERT TestData
SELECT 1, 10
UNION ALL
SELECT 1, 10
UNION ALL
SELECT 1, 5
UNION ALL
SELECT 1, 11
UNION ALL
SELECT 2, 20
UNION ALL
SELECT 2, 2
UNION ALL
SELECT 2, 10
UNION ALL
SELECT 3, 27
UNION ALL
SELECT 3, 3;
DECLARE @param INT = 25;
CREATE TABLE #Results --or table variable
(
TestDataID INT NOT NULL
,ProductID INT NOT NULL
,SalesQty INT NOT NULL
,RowNumber INT NOT NULL
,PRIMARY KEY(RowNumber, ProductID)
);
INSERT #Results(TestDataID, ProductID, SalesQty, RowNumber)
SELECT a.TestDataID, a.ProductID, a.SalesQty,
ROW_NUMBER() OVER(PARTITION BY a.ProductID ORDER BY a.TestDataID) RowNumber
FROM TestData a;
;WITH CteRecursive
AS
(
SELECT a.ProductID
,a.RowNumber
,a.TestDataID
,a.SalesQty
,a.SalesQty AS RunningTotal
FROM #Results a
WHERE a.RowNumber = 1
AND a.SalesQty <= @param
UNION ALL
SELECT crt.ProductID
,crt.RowNumber
,crt.TestDataID
,crt.SalesQty
,prev.RunningTotal + crt.SalesQty
FROM #Results crt
INNER JOIN CteRecursive prev ON prev.ProductID = crt.ProductID
AND prev.RowNumber + 1 = crt.RowNumber
WHERE prev.RunningTotal + crt.SalesQty <= @param
)
SELECT a.TestDataID
,a.ProductID
,a.SalesQty
,a.RunningTotal
FROM CteRecursive a
ORDER BY a.ProductID, a.RowNumber;
DROP TABLE #Results;
DROP TABLE TestData;
结果:
TestDataID ProductID SalesQty RunningTotal
----------- ----------- ----------- ------------
2 1 10 10
4 1 10 20
6 1 5 25
10 2 20 20
12 2 2 22