SQL存储过程添加值并在达到最大值后停止

时间:2012-03-14 21:45:55

标签: sql sql-server conditional-statements

我想编写一个SQL查询(SQL Server),它将返回行(按给定的顺序),但只返回给定的总数。我的客户已付给我一定的金额,我想只返回那些< =到那个金额的行。

例如,如果客户付了我370美元,表中的数据是

 id amount
 1  100
 2  122
 3  134
 4  23
 5  200

然后我想只返回第1,2和3行

这需要高效,因为会有数千行,所以for循环不是理想的,我想。或者SQL Server是否足够高效以使用for循环优化存储过程?

提前致谢。吉姆。

3 个答案:

答案 0 :(得分:3)

有两种选择。

1)三角连接

 SELECT *
 FROM YourTable Y1
 WHERE (SELECT SUM(amount) 
        FROM YourTable Y2
        WHERE Y1.id >= Y2.id ) <= 370

2)递归CTE

WITH    RecursiveCTE
AS      (
        SELECT TOP 1 id, amount, CAST(amount AS BIGINT) AS Total
        FROM YourTable
        ORDER BY id
        UNION   ALL
        SELECT  R.id, R.amount, R.Total
        FROM    (
                SELECT  T.*,
                        T.amount + Total AS Total,
                        rn = ROW_NUMBER() OVER (ORDER BY T.id)
                FROM    YourTable T
                JOIN    RecursiveCTE R
                        ON  R.id < T.id
                ) R
        WHERE   R.rn = 1 AND Total <= 370
        )
SELECT  id, amount, Total
FROM    RecursiveCTE
OPTION  (MAXRECURSION 0);  

第二个可能表现更好。

在SQL Server 2012中,您将能够像

这样的东西
;WITH CTE AS
(
SELECT id, 
       amount,
       SUM(amount) OVER(ORDER BY id  
                        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
          AS RunningTotal
  FROM YourTable 
  )
  SELECT *
  FROM CTE
  WHERE RunningTotal <=370

虽然可能会有更有效的方法(一旦达到总数就停止扫描)

答案 1 :(得分:0)

直接进场:

SELECT a.id, a.amount
FROM table1 a
INNER JOIN table1 b ON (b.id <=a.id)
GROUP BY a.id, a.amount
HAVING SUM(b.amount) <= 370

不幸的是,它有N ^ 2性能问题。

答案 2 :(得分:0)

类似的东西:

select id from 
(
select t1.id, t1.amount, sum( t2.amount ) s 
from tst t1, tst t2
where t2.id <= t1.id
group by t1.id, t1.amount
) 
where s < 370