表
create table tst(locationId int,
scheduleCount tinyint(1) DEFAULT 0,
displayFlag tinyint(1) DEFAULT 0);
INSERT INTO tst(locationId,scheduleCount)
values(5,0),(2,0),(5,1),(5,2),(2,1),(2,2);
我使用一个查询更新多行和多列,但是只想为第一行更改其中一列,并保持该列的其他内容相同。
我想用一些位置ID更新所有行,并将displayFlag更改为1,并将只有顶部条目的scheduleCount增加为1,其余将保持不变
**查询**
update tst,(select @rownum:=0) r,
set tst.displayFlag =1,
scheduleCount = (CASE WHEN @rownum=0
then scheduleCount+1
ELSE scheduleCount
END),
@rownum:=1 where locationId = 5
但是它给出了错误并且没有设置用户定义的变量 rownum ,我能够在一个select中加入表并更改rownum的值,有没有其他方法可以更新值。
答案 0 :(得分:1)
我不确定这是做这种事情的正确方法,但是可以在CASE
条件中包含用户变量逻辑:
UPDATE tst
JOIN (SELECT @first_row := 1) r
SET tst.displayFlag = 1,
scheduleCount = CASE
WHEN @first_row = 1 AND ((@first_row := 0) OR TRUE) THEN scheduleCount+1
ELSE scheduleCount
END
WHERE locationId = 5;
我使用了@first_row
标记,因为这与您的初始尝试更为一致。
CASE
的工作原理如下:
在第一行@first_row = 1
上,处理WHEN
之后的AND
的第二部分,设置@first_row := 0
。对我们来说不幸的是,作业返回0
,因此OR TRUE
会确保整个条件为TRUE
。因此使用了scheduleCount + 1
。
在第二行@first_row != 1
上,条件为FALSE
,WHEN
后AND
的第二部分未经处理,ELSE scheduleCount
} 用来。
您可以在此SQL Fiddle中看到它正常工作。注意;我必须将列类型设置为TINYINT(3)
才能获得正确的结果。
N.B。如果没有ORDER BY
,则无法保证' 1st'排;即使它是由SELECT * FROM tst
返回的第一个。
<强>更新强>
不幸的是,如果有加入,则无法添加ORDER BY
,所以您可以选择:
在查询外部初始化@first_row
并移除JOIN
。
否则,最好将查询重写为类似于:
的内容UPDATE tst
JOIN (
SELECT locationId,
scheduleCount,
displayFlag,
@row_number := @row_number + 1 AS row_number
FROM tst
JOIN (SELECT @row_number := 0) init
WHERE locationId = 5
ORDER BY scheduleCount DESC
) tst2
ON tst2.locationId = tst.locationId
AND tst2.scheduleCount = tst.scheduleCount
AND tst2.displayFlag = tst.displayFlag
SET tst.displayFlag = 1,
tst.scheduleCount = CASE
WHEN tst2.row_number = 1 THEN tst.scheduleCount+1
ELSE tst.scheduleCount
END;
或写两个查询:
UPDATE tst
SET displayFlag = 1
WHERE locationId = 5;
UPDATE tst
SET scheduleCount = scheduleCount + 1
WHERE locationId = 5
ORDER BY scheduleCount DESC
LIMIT 1;