2

测试语句:</p>

create table #t
(
  isid int primary key identity(1,1),
  amount decimal(18,2)
)
go

insert into #t values(23.43)
insert into #t values(213.43)
insert into #t values(523.3)
insert into #t values(23.4)
insert into #t values(263.23)
insert into #t values(223.43)

drop table #t

如何通过 isid 获得小于一个值(例如 500)的“总和”?有一个说法

select * from #t as a where exists(select 1 from #t where isid<=a.isid having sum(amount)<500)

但它有一个错误。当第一个值大于 500 且第二个值为负数时。

前任:

insert into #t values(503.43)
insert into #t values(-13.43)

结果将只有一个值(-13.43)。

4

4 回答 4

1

为了实现这一点,我认为我们可以为集合中的所有值生成运行总计,并选择总和小于 500 的最大“isid”。

    create table T
    (
      isid int primary key identity(1,1),
      amount decimal(18,2)
    )
    go

    insert into T values(503.43)
    insert into T values(-13.43)
    insert into T values(5.00)
    insert into T values(1.00)
    insert into T values(55.00)

SELECT isid
FROM T
WHERE isid <= 
(
  SELECT MAX(B.isid)
  FROM
    (
      SELECT
      T1.isid,
      T1.Amount,
      SUM(T2.Amount) AS SummedAmount
      FROM T T1
      INNER JOIN T T2 ON T2.isid <= T1.isid
      GROUP BY T1.isid, T1.Amount
      HAVING SUM(T2.Amount) < 500
    ) B
)

这是一个 SQLFiddle: http ://www.sqlfiddle.com/#!3/968af/4

于 2013-04-18T14:38:44.947 回答
0

@Lamak 如果在您的第​​一个测试数据中插入 -800 作为最后一行会发生什么? 结果图片

于 2013-04-18T15:09:35.443 回答
0

这是一种获取最大累积总和小于 500 的 isid 的方法,假设 isid 是按顺序编号的,没有间隙:

select minisid - 1
from (select MIN(isid) as minisid
      from (select *, (select SUM(amount) from #t t2 where t2.isid <= t.isid) as cumsum
            from #t t
           ) t
      where cumsum >= 500
     ) t

如果您想在第二种情况下不返回任何行,请添加子句:

where minisid > 1
于 2013-04-18T15:01:00.970 回答
0

如果您使用的是 SQL-Server 版本,则可以使用该OVER ()子句的增强:

WITH cte AS
( SELECT
      isid,
      SUM(Amount) OVER (ORDER BY isid
                        ROWS BETWEEN UNBOUNDED PRECEDING
                                 AND CURRENT ROW
                       ) AS sum_amount
  FROM t
)
SELECT MAX(isid)
FROM cte
WHERE sum_amount < 500 ;
于 2013-04-18T17:04:23.880 回答