从SUM(列)25呢?SQL 2005中引入了公共表扩展,因此如果OP尝试您的查询或我的查询,他将非常困惑。这不是我们的错,没错。但是,我没有看到任何关于SQLServer版本的参考资料。我想是2005年。对于SQLServer200020052008,可以使用Jeff Moden或cursors描述的古怪更新方法。 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 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) 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
我试图选择前n行数,其中列的和小于或等于作为变量传入的数字 表十:从SUM(列)25呢?SQL 2005中引入了公共表扩展,因此如果OP尝试您的查询或我的查询,他将非常困惑。这不是我们的错,没错。但是,我没有看到任何关于SQLServer版本的参考资料。我想是2005年。对于SQLServer200020052008,可以使用Jeff Moden或cursors描述的古怪更新方法。 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 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) 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,sql,sql-server,Sql,Sql Server,我试图选择前n行数,其中列的和小于或等于作为变量传入的数字 表十: Col1 Col2 1 10 2 10 3 5 4 20 所以我基本上是想做这样的事情: SELECT * FROM TableX WHERE SUM(Col2) <= 25 你在找这个条款 不幸的是,我现在无法访问sql server来测试完整的解决方案,但是。。。在mysql中,这似乎正是您想要的,如果我没有弄错的话,它也应该为T-SQL做这件事 SELECT A.Col1, A.
Col1 Col2
1 10
2 10
3 5
4 20
所以我基本上是想做这样的事情:
SELECT * FROM TableX WHERE SUM(Col2) <= 25
你在找这个条款
不幸的是,我现在无法访问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
以下是您需要的内容,包括概念验证:
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
编辑:请不要将TestDataID identity1,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;
这不是OP首先要求的,谢谢你的帮助。我必须道歉,但我已经多年没有接触SQL了,因此我来到这里。我试过你的建议,但似乎没有什么效果。相反,它只是返回Col2+1的所有记录,为什么投票失败??如果你要投票反对某人成为一个男人,并公布你的理由,否则你只是一个哭哭啼啼的懦夫@马克拉姆:因为在我编辑之前的几秒钟,我有一个错误的答案,这就是它的工作原理。@Kris,我不是在评论你的帖子,我是在评论那个否决你的懦夫,但我支持你。任何想要否决某人的人都应该被要求解释为什么他们觉得有必要这样做。当所有4行在Col1中都没有公共值时,这可能吗?因为,根据你的例子,这也可能是一个有效的结果:Col1 Col2 3 5 4 20我假设你在寻找类似于运行总数的东西是正确的吗?如果是这种情况,您是按col1还是col2排序?如果您有100000+1组呢?而且,如果Col1有重复的值呢?Top100000只是为了在这里需要的子选择中进行订购。您可以将其设置为更高的值。但是,它应该附带一个警告,说明它是半个叉积。100行将在GROUP BY之前产生5050行。1000行将在分组之前产生500500行。一百万张唱片会让你大吃一惊。@Dems你说得对。然而,尽管有可能,但真正的情况是不可能发生的。在应用此方法之前,您很可能会过滤原始数据。@Adrian我不明白为什么会有前100名。。。order by在子查询中,为什么不在runningtotal的外部排序呢?如果第一行row=1的Col2>25呢?SQL 2005中引入了公共表扩展,因此如果OP尝试您的查询或我的查询,他将非常困惑。这不是我们的错,没错。但是,我没有看到任何关于SQLServer版本的参考资料。我想是2005年。对于SQLServer200020052008,可以使用Jeff Moden或cursors描述的古怪更新方法。
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
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)
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