sql 根据当前行的值对前几行求和
sql sum previous rows based on value of current row
我有以下 table
CREATE TABLE #tbl (
RoomTypeId INT NOT NULL,
DayNo TINYINT NOT NULL,
RoomNo TINYINT NOT NULL,
IsDormitory BIT,
AdultsNo TINYINT NOT NULL,
Tmp TINYINT)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 1, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 1, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 2, 1, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 2, 1, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2487, 98, 1, 0, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2487, 99, 1, 0, 2, 0)
仅对于 IsDormitory = 1 的那些行,我想使用如下值更新字段 Tmp:对于具有特定 RoomNo 的每个房间,Tmp 列 = RoomNo <= 当前所有房间的所有 AdultsNo 的总和房间号
示例:
- 对于 RoomNo = 1,Tmp = 1 位成人的房间,
- 对于RoomNo = 2的房间,Tmp = 3位成人,即1位成人(对应RoomNo = 1)+ 2位成人(对应RoomNo = 2)
结果将是:
RoomTypeId DayNo RoomNo IsDormitory AdultsNo Tmp
2486 98 1 1 1 1
2486 99 1 1 1 1
2486 98 2 1 2 3
2486 99 2 1 2 3
2487 98 1 0 2 0
2487 99 1 0 2 0
以下无效:
update #tmp2 set TmpAdults = Adults from #tmp2 t inner join
(select RoomTypeId, DayNo, sum(AdultsNo) as Adults from #tmp2 x where x.RoomNo < t.RoomNo) s on t.RoomTypeId = s.RoomTypeId and t.DayNo = s.DayNo
;with CTE as
(
select RoomTypeId, DayNo, sum(AdultsNo) as Adults from #tmp2 group by RoomTypeId, DayNo
)
update #tmp2 set TmpAdults = c.Adults from #tmp2 t
inner join CTE c on t.RoomTypeId = c.RoomTypeId and t.DayNo = c.DayNo
我正在使用 Microsoft SQL Server 2014。
我不知道如何使用 CTE,但根据我的阅读,这应该是答案。
谢谢。
更新:
我添加了 2 行:
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 3, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 3, 1, 1, 0)
但不幸的是答案并不如我所料。我希望 RoomNo = 3 Tmp = 1+2+1=4,而不是我得到 2
RoomTypeId DayNo RoomNo IsDormitory AdultsNo Tmp
2486 98 3 1 1 4
2486 99 3 1 1 4
您可以使用 CTE
来更新:
;WITH ToUpdate AS (
SELECT t1.AdultsNo + COALESCE(t3.AdultsNo,0) AS AdultsNo,
Tmp
FROM #tbl AS t1
OUTER APPLY (
SELECT DISTINCT AdultsNo
FROM #tbl AS t2
WHERE t2.RoomNo < t1.RoomNo) AS t3
WHERE IsDormitory = 1
)
UPDATE ToUpdate
SET Tmp = AdultsNo
CTE
使用 OUTER APPLY
操作来获取先前记录(如果有)的 AdultsNo
值。
此 CTE 应该会为您提供结果,然后它很简单 JOIN
并执行更新。
不过你对多个临时表的使用让我担心...
;WITH MyCTE AS
(
SELECT
RoomTypeID,
DayNo,
RoomNo,
IsDormitory,
AdultsNo,
SUM(CASE WHEN IsDormitory = 1 THEN AdultsNo ELSE 0 END) OVER (PARTITION BY RoomTypeID, DayNo ORDER BY RoomNo ROWS UNBOUNDED PRECEDING) AS Tmp
FROM
#tbl
)
SELECT *
FROM MyCTE
update #tbl
set Tmp = (
select sum(t2.AdultNo) from #tbl t2
where t2.RoomTypeID = #tbl.RoomTypeID and t2.DayNo = #tbl.DayNo
and t2.RoomNo <= #tbl.RoomNo
)
where IsDormitory = 1
我相信 MySQL 在更新的子查询中引用相同的 table 有问题,但我很确定 SQL 服务器对此没有问题。您可以使用别名在内部查询中进行关联,但这确实不标准 SQL。请注意,内部查询不限于宿舍房间,因为从问题中不清楚这就是您所需要的。
我有以下 table
CREATE TABLE #tbl (
RoomTypeId INT NOT NULL,
DayNo TINYINT NOT NULL,
RoomNo TINYINT NOT NULL,
IsDormitory BIT,
AdultsNo TINYINT NOT NULL,
Tmp TINYINT)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 1, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 1, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 2, 1, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 2, 1, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2487, 98, 1, 0, 2, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2487, 99, 1, 0, 2, 0)
仅对于 IsDormitory = 1 的那些行,我想使用如下值更新字段 Tmp:对于具有特定 RoomNo 的每个房间,Tmp 列 = RoomNo <= 当前所有房间的所有 AdultsNo 的总和房间号
示例:
- 对于 RoomNo = 1,Tmp = 1 位成人的房间,
- 对于RoomNo = 2的房间,Tmp = 3位成人,即1位成人(对应RoomNo = 1)+ 2位成人(对应RoomNo = 2)
结果将是:
RoomTypeId DayNo RoomNo IsDormitory AdultsNo Tmp
2486 98 1 1 1 1
2486 99 1 1 1 1
2486 98 2 1 2 3
2486 99 2 1 2 3
2487 98 1 0 2 0
2487 99 1 0 2 0
以下无效:
update #tmp2 set TmpAdults = Adults from #tmp2 t inner join
(select RoomTypeId, DayNo, sum(AdultsNo) as Adults from #tmp2 x where x.RoomNo < t.RoomNo) s on t.RoomTypeId = s.RoomTypeId and t.DayNo = s.DayNo
;with CTE as
(
select RoomTypeId, DayNo, sum(AdultsNo) as Adults from #tmp2 group by RoomTypeId, DayNo
)
update #tmp2 set TmpAdults = c.Adults from #tmp2 t
inner join CTE c on t.RoomTypeId = c.RoomTypeId and t.DayNo = c.DayNo
我正在使用 Microsoft SQL Server 2014。
我不知道如何使用 CTE,但根据我的阅读,这应该是答案。 谢谢。
更新:
我添加了 2 行:
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 98, 3, 1, 1, 0)
insert into #tbl (RoomTypeId, DayNo, RoomNo, IsDormitory, AdultsNo, Tmp) values(2486, 99, 3, 1, 1, 0)
但不幸的是答案并不如我所料。我希望 RoomNo = 3 Tmp = 1+2+1=4,而不是我得到 2
RoomTypeId DayNo RoomNo IsDormitory AdultsNo Tmp
2486 98 3 1 1 4
2486 99 3 1 1 4
您可以使用 CTE
来更新:
;WITH ToUpdate AS (
SELECT t1.AdultsNo + COALESCE(t3.AdultsNo,0) AS AdultsNo,
Tmp
FROM #tbl AS t1
OUTER APPLY (
SELECT DISTINCT AdultsNo
FROM #tbl AS t2
WHERE t2.RoomNo < t1.RoomNo) AS t3
WHERE IsDormitory = 1
)
UPDATE ToUpdate
SET Tmp = AdultsNo
CTE
使用 OUTER APPLY
操作来获取先前记录(如果有)的 AdultsNo
值。
此 CTE 应该会为您提供结果,然后它很简单 JOIN
并执行更新。
不过你对多个临时表的使用让我担心...
;WITH MyCTE AS
(
SELECT
RoomTypeID,
DayNo,
RoomNo,
IsDormitory,
AdultsNo,
SUM(CASE WHEN IsDormitory = 1 THEN AdultsNo ELSE 0 END) OVER (PARTITION BY RoomTypeID, DayNo ORDER BY RoomNo ROWS UNBOUNDED PRECEDING) AS Tmp
FROM
#tbl
)
SELECT *
FROM MyCTE
update #tbl
set Tmp = (
select sum(t2.AdultNo) from #tbl t2
where t2.RoomTypeID = #tbl.RoomTypeID and t2.DayNo = #tbl.DayNo
and t2.RoomNo <= #tbl.RoomNo
)
where IsDormitory = 1
我相信 MySQL 在更新的子查询中引用相同的 table 有问题,但我很确定 SQL 服务器对此没有问题。您可以使用别名在内部查询中进行关联,但这确实不标准 SQL。请注意,内部查询不限于宿舍房间,因为从问题中不清楚这就是您所需要的。