sql根据当前行

时间:2016-02-24 18:03:54

标签: sql sql-update common-table-expression sql-server-2014

我有下表

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 =所有房间的所有AdultsNo的总和没有RoomNo< = current RoomNo

示例:

  • 适用于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 

3 个答案:

答案 0 :(得分:1)

您可以使用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值(如果有)。

答案 1 :(得分:1)

此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

答案 2 :(得分:0)

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在更新的子查询中引用同一个表时遇到问题,但我非常确定SQL Server没有问题。您可以使用别名来关联内部查询,但这实际上不是标准SQL。请注意,内部查询不仅限于宿舍,因为问题并不清楚这是您需要的。