sql查询求和问题(sqlserver2008r2)

时间:2021-02-09 18:50:54
有这样一张表
table A
字段
code varchar(20),
tv  datetime,
value varchar(20)


数据则是如下:
CODE                 TV                        VALUE
2000            2013-12-05 00:00:00.000           0.5
2000            2013-12-06 00:00:00.000           1.5
2000            2013-12-07 00:00:00.000           2.3
2000            2013-12-08 00:00:00.000           0.4
2000            2013-12-09 00:00:00.000           4.1
2000            2013-12-10 00:00:00.000           0.1

如何用sql得到以下的数据?
CODE                 TV                        VALUE                SUM
2000            2013-12-05 00:00:00.000           0.5           0.5+1.5+2.3
2000            2013-12-06 00:00:00.000           0.5           1.5+2.3+0.4
2000            2013-12-07 00:00:00.000           0.5           2.3+0.4+4.1
2000            2013-12-08 00:00:00.000           0.5           0.4+4.1+0.1

SUM这一列的含义是    取当前行数据时间及其后两天的行数据的VALUE值之和

另外,数据条数会减少一些,因为2013-12-09日的数据没有了11日的数据后无法计算  只需要计算到09日即可   这个时间可以显示的设置(意思就是最终的sql中可以加上tv<=2013-12-08)

不知道这种求和函数怎么写。要求只用SQL,不能用存储过程之类的

10 个解决方案

#1



create table tableA(code varchar(20),
tv  datetime,
value numeric(10,1)
)

insert into tableA
select 2000,'2013-12-05 00:00:00.000',0.5
union all select 2000,'2013-12-06 00:00:00.000',1.5
union all select 2000,'2013-12-07 00:00:00.000',2.3
union all select 2000,'2013-12-08 00:00:00.000',0.4
union all select 2000,'2013-12-09 00:00:00.000',4.1
union all select 2000,'2013-12-10 00:00:00.000',0.1
go

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'
drop table tableA

/*
code    tv    value    sum
----------------------------------------------------
2000 2013-12-05 00:00:00.000 .5 4.3
2000 2013-12-06 00:00:00.000 1.5 4.2
2000 2013-12-07 00:00:00.000 2.3 6.8
2000 2013-12-08 00:00:00.000 .4 4.6
*/

#2


select code,
       tv,
       value,
       (SELECT sum(cast(isnull(VALUE, 0) as decimal(10, 3)))
          FROM A as I
         WHERE DATEDIFF(day, O.tv, I.tv) >= 0
           and DATEDIFF(day, O.tv, I.tv) <= 2) as sumvalue
  from A as O

#3


2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?

#4


引用 3 楼 xiesisi3 的回复:
2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?

方案1:把子查询替换A
方案2:把子查询的结果插入临时表,建立适当的索引,然后把代码中的A替换成临时表名,这个方法我个人比较推荐

#5


引用 3 楼 xiesisi3 的回复:
2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?


1、你可以用cte,这个比较方便:
;with tableA
as
(
你的子查询语句
)

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'


2、就是临时表,不过这个就是多个语句了,不是一个语句:
if OBJECT_ID('tempdb..#tableA') is not null
   drop table #tableA


select * into #tableA
from 你的子查询语句


select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from #tableA a
where tv<='2013-12-08'

#6


修改一下:

1、你可以用cte,这个比较方便:
;with tableA
as
(
你的子查询语句
)

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'


2、就是临时表,不过这个就是多个语句了,不是一个语句, 改了一下
if OBJECT_ID('tempdb..#tableA') is not null
   drop table #tableA


select * into #tableA
from 你的子查询语句


select *,[sum]=(select sum(VALUE) from #tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from #tableA a
where tv<='2013-12-08'

#7


该回复于2013-12-18 11:24:42被管理员删除

#8


由于实际表数据里的日期(TV字段)是动态的,所以最好不要在sql里加上tv<=2013-12-08.

create table tableA
(code varchar(20),tv datetime,value varchar(20))

insert into tableA
 select '2000','2013-12-05 00:00:00.000','0.5' union all
 select '2000','2013-12-06 00:00:00.000','1.5' union all
 select '2000','2013-12-07 00:00:00.000','2.3' union all
 select '2000','2013-12-08 00:00:00.000','0.4' union all
 select '2000','2013-12-09 00:00:00.000','4.1' union all
 select '2000','2013-12-10 00:00:00.000','0.1'


with t as
(select code,tv,value,
        row_number() over(partition by code order by tv) 'rn'
 from tableA)
select a.code,a.tv,a.value,
       cast(a.value as decimal(5,1))+
       cast(b.value as decimal(5,1))+
       cast(c.value as decimal(5,1)) 'SUM'
 from t a
 left join t b on a.rn=b.rn-1
 left join t c on a.rn=c.rn-2
 where b.rn is not null and c.rn is not null

/*
code                 tv                      value                SUM
-------------------- ----------------------- -------------------- --------
2000                 2013-12-05 00:00:00.000 0.5                  4.3
2000                 2013-12-06 00:00:00.000 1.5                  4.2
2000                 2013-12-07 00:00:00.000 2.3                  6.8
2000                 2013-12-08 00:00:00.000 0.4                  4.6

(4 row(s) affected)
*/

#9


请学习楼上的写法,其实这个语句很简单的

#10


引用 2 楼 x_wy46 的回复:
select code,
       tv,
       value,
       (SELECT sum(cast(isnull(VALUE, 0) as decimal(10, 3)))
          FROM A as I
         WHERE DATEDIFF(day, O.tv, I.tv) >= 0
           and DATEDIFF(day, O.tv, I.tv) <= 2) as sumvalue
  from A as O


上述子查询中的WHERE条件要优化一下 I.tv >= O.tv AND I.tv <= O.tv + 2

#1



create table tableA(code varchar(20),
tv  datetime,
value numeric(10,1)
)

insert into tableA
select 2000,'2013-12-05 00:00:00.000',0.5
union all select 2000,'2013-12-06 00:00:00.000',1.5
union all select 2000,'2013-12-07 00:00:00.000',2.3
union all select 2000,'2013-12-08 00:00:00.000',0.4
union all select 2000,'2013-12-09 00:00:00.000',4.1
union all select 2000,'2013-12-10 00:00:00.000',0.1
go

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'
drop table tableA

/*
code    tv    value    sum
----------------------------------------------------
2000 2013-12-05 00:00:00.000 .5 4.3
2000 2013-12-06 00:00:00.000 1.5 4.2
2000 2013-12-07 00:00:00.000 2.3 6.8
2000 2013-12-08 00:00:00.000 .4 4.6
*/

#2


select code,
       tv,
       value,
       (SELECT sum(cast(isnull(VALUE, 0) as decimal(10, 3)))
          FROM A as I
         WHERE DATEDIFF(day, O.tv, I.tv) >= 0
           and DATEDIFF(day, O.tv, I.tv) <= 2) as sumvalue
  from A as O

#3


2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?

#4


引用 3 楼 xiesisi3 的回复:
2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?

方案1:把子查询替换A
方案2:把子查询的结果插入临时表,建立适当的索引,然后把代码中的A替换成临时表名,这个方法我个人比较推荐

#5


引用 3 楼 xiesisi3 的回复:
2#的方法没测,1#的方法可用,而且提供了我解决问题的思路,谢谢二位。

不过,还想追加问题
如果A不是一张表,而是一个数据量比较大的(大概几万条数据15行左右的sql代码)子查询呢?


1、你可以用cte,这个比较方便:
;with tableA
as
(
你的子查询语句
)

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'


2、就是临时表,不过这个就是多个语句了,不是一个语句:
if OBJECT_ID('tempdb..#tableA') is not null
   drop table #tableA


select * into #tableA
from 你的子查询语句


select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from #tableA a
where tv<='2013-12-08'

#6


修改一下:

1、你可以用cte,这个比较方便:
;with tableA
as
(
你的子查询语句
)

select *,[sum]=(select sum(VALUE) from tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from tableA a
where tv<='2013-12-08'


2、就是临时表,不过这个就是多个语句了,不是一个语句, 改了一下
if OBJECT_ID('tempdb..#tableA') is not null
   drop table #tableA


select * into #tableA
from 你的子查询语句


select *,[sum]=(select sum(VALUE) from #tableA b where b.tv>=a.tv and b.tv<=dateadd(day,2,a.tv))
from #tableA a
where tv<='2013-12-08'

#7


该回复于2013-12-18 11:24:42被管理员删除

#8


由于实际表数据里的日期(TV字段)是动态的,所以最好不要在sql里加上tv<=2013-12-08.

create table tableA
(code varchar(20),tv datetime,value varchar(20))

insert into tableA
 select '2000','2013-12-05 00:00:00.000','0.5' union all
 select '2000','2013-12-06 00:00:00.000','1.5' union all
 select '2000','2013-12-07 00:00:00.000','2.3' union all
 select '2000','2013-12-08 00:00:00.000','0.4' union all
 select '2000','2013-12-09 00:00:00.000','4.1' union all
 select '2000','2013-12-10 00:00:00.000','0.1'


with t as
(select code,tv,value,
        row_number() over(partition by code order by tv) 'rn'
 from tableA)
select a.code,a.tv,a.value,
       cast(a.value as decimal(5,1))+
       cast(b.value as decimal(5,1))+
       cast(c.value as decimal(5,1)) 'SUM'
 from t a
 left join t b on a.rn=b.rn-1
 left join t c on a.rn=c.rn-2
 where b.rn is not null and c.rn is not null

/*
code                 tv                      value                SUM
-------------------- ----------------------- -------------------- --------
2000                 2013-12-05 00:00:00.000 0.5                  4.3
2000                 2013-12-06 00:00:00.000 1.5                  4.2
2000                 2013-12-07 00:00:00.000 2.3                  6.8
2000                 2013-12-08 00:00:00.000 0.4                  4.6

(4 row(s) affected)
*/

#9


请学习楼上的写法,其实这个语句很简单的

#10


引用 2 楼 x_wy46 的回复:
select code,
       tv,
       value,
       (SELECT sum(cast(isnull(VALUE, 0) as decimal(10, 3)))
          FROM A as I
         WHERE DATEDIFF(day, O.tv, I.tv) >= 0
           and DATEDIFF(day, O.tv, I.tv) <= 2) as sumvalue
  from A as O


上述子查询中的WHERE条件要优化一下 I.tv >= O.tv AND I.tv <= O.tv + 2