在SQL Server上SUM(列)=值时返回行

时间:2017-03-09 10:14:03

标签: sql sql-server sum

我的表:

id int(11) AUTO_INCREMENT
date date
number int(3)

+----+------------+--------+
| id | date       | number |
+----+------------+--------+    
| 1  | 2010-01-02 |   0    |
| 2  | 2010-01-03 |   3    |
| 3  | 2010-01-04 |   0    |
| 4  | 2010-01-05 |   2    |
| 5  | 2010-01-06 |   1    |
| 6  | 2010-01-07 |   3    |
+----+------------+--------+

我想返回数字的和为6且日期>的日期。 '2010-01-04'

我希望返回添加字段编号等于6的日期(在特定日期之后,在此示例中为2010-01-04)。示例:我的查询应返回2010-01-07,因为2010-01-05中的2 2010-01-06中的2 2010-01-07中的2

到目前为止,我在MySQL服务器上使用过这个查询:

select date 
    from 
      (select date, @n:=@n+total total 
          from 
            (select date, sum(number) total 
                from MyTable 
              where date > '2010-01-04' 
              group by date 
              order by date 
            ) t 
           cross join 
            (select @n:=0) n 
      ) tt 
   where total = 6

现在,我们在SQL Server上只有一台服务器,并且在SQL Server上使用此查询时遇到了一些问题。

3 个答案:

答案 0 :(得分:1)

在这种情况下,你可以使用它:

with calc as 
(
    select top 100 percent
                t1.id, t1.dt, SUM(t2.num) acm
    from        MyTable t1
    inner join  MyTable t2 on t1.id >= t2.id
    group by    t1.id, t1.dt
    order by    t1.id
)
select top 1 id, dt as Date, Acm
from   calc
where  Acm >= 6;

结果:

|id|Date               |Acm|
|-:|:------------------|--:|
| 5|06/01/2010 00:00:00|  6|

另一种方法:

with calc2 as
(
    select id, dt, sum(num) over (order by dt) acm
    from @csum
)
select top 1 id, dt as Date, Acm
from   calc2
where  Acm >= 6;

检查 dbfiddle here

<强>更新

如果每次累积总和达到6时需要一个复位点,那就复杂了。

with calc2 as
(
    select id, dt, num,
           sum(num) over (order by dt) acm, 
           sum(num) over (order by dt) / 6 reset
    from @csum
)
select id, dt as Date
from   @csum
where  id in (select min(id) from calc2 t2 where reset > 0 group by reset);

每次累计总和达到6时,第一个CTE设置一个复位点。(请记住,当SUM()= 6时它会重置

第二个查询返回每个&#39; reset&#39;的第一行。分区。

(select min(id) from calc2 t2 where reset > 0 group by reset)

尝试 dbfiddle here

答案 1 :(得分:0)

为什么不试试这个:

WITH
-- input, don't use in real query
input(id,the_date,the_number) AS (
          SELECT 1,DATE '2010-01-02',0
UNION ALL SELECT 2,DATE '2010-01-03',3
UNION ALL SELECT 3,DATE '2010-01-04',0
UNION ALL SELECT 4,DATE '2010-01-05',2
UNION ALL SELECT 5,DATE '2010-01-06',1
UNION ALL SELECT 6,DATE '2010-01-07',3
)
-- end of input, start "real" WITH clause here
,
run_sum AS (
SELECT
  *
, SUM(the_number) OVER(ORDER BY id) AS the_sum
FROM input
WHERE the_date > '2010-01-04'
)
-- the above returns:
-- SELECT * FROM run_sum;
-- id|the_date  |the_number|the_sum
--  4|2010-01-05|         2|      2
--  5|2010-01-06|         1|      3
--  6|2010-01-07|         3|      6
SELECT
  the_date
FROM run_sum
WHERE the_sum = 6
;

答案 2 :(得分:0)

如果你有MSSQL 2012,你可以试试这个:

SELECT DATE 
    FROM 
      (SELECT DATE, SUM(TOTAL) OVER (ORDER BY DATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS TOTAL
          FROM 
            (SELECT DATE, SUM(NUMBER) TOTAL 
                FROM MYTABLE
              WHERE DATE > CONVERT(DATE, '2010-01-04',121) 
              GROUP BY DATE               
            ) T         
      ) TT 
   WHERE TOTAL = 6