更新多行,但只有第一行具有不同的值

时间:2015-06-02 11:07:29

标签: mysql join

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的值,有没有其他方法可以更新值。

1 个答案:

答案 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上,条件为FALSEWHENAND的第二部分未经处理,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;