我有update
语句,如下所示:
update user_stats set
requestsRecd = (select count(*) from requests where requestedUserId = 1) where userId = 1,
requestsSent = (select count(*) from requests where requesterUserId = 2) where userId = 2;
我正在尝试做的是更新同一个表,但该表中的不同用户,一个用户收到的好友请求数,以及另一个用户发送的好友请求数。
如果我删除了where
子句,那么我正在做的是什么,然后,它会更新整个表中的所有用户。
我知道如何使用where
条款执行此类操作,或使用其他方法获得相同的结果?
答案 0 :(得分:2)
(正如在其他几个答案中提出的那样,显然,您可以运行两个单独的陈述,但要回答您提出的问题,是否可能,以及如何做到这一点...... )< / p>
是的,可以使用单个语句完成更新操作。您需要将条件测试作为语句的一部分(例如示例的WHERE子句中的条件,但这些条件不能进入UPDATE语句的WHERE子句。
我们在一个UPDATE语句中执行此操作的一个重要限制是,该语句必须为列的两个分配一个值,对于两个行。
我们可以利用的一个“技巧”是将列的当前值分配回列,例如
UPDATE mytable SET mycol = mycol WHERE ...
这导致列中存储的内容无变化。 (那仍然会在满足WHERE子句的行的BEFORE / AFTER更新触发器上触发,但当前存储在列中的值将不改变。)
因此,我们无法有条件地指定要在哪些行上更新哪些列,但我们可以在我们分配给的表达式中包含一个条件专栏。例如,请考虑:
UPDATE mytable SET mycol = IF(foo=1, 'bar', mycol)
对于foo = 1的行计算为TRUE,我们将“bar”分配给列。对于所有其他行,列的值将保持不变。
在您的情况下,如果特定条件为真,您希望为列分配“新”值,否则保持不变。
考虑这个陈述的结果:
UPDATE user_stats t
SET t.requestsRecd = IF(t.userId=1, expr1, t.reqestsRecd)
, t.requestsSent = IF(t.userId=2, expr2, t.reqestsSent)
WHERE t.userId IN (1,2);
(我省略了返回您要分配的计数值的子查询,并将其替换为“expr1”和“expr2”占位符。这样可以更容易地查看模式,而不会使其更加混乱语法,隐藏模式。)
您可以使用返回计数的原始子查询替换上述语句中的expr1
和expr2
。
作为替代形式,还可以在单行上返回这些计数,使用内联视图(此处别名为v
),然后指定连接操作。像这样:
UPDATE user_stats t
CROSS
JOIN ( SELECT (select count(*) from requests where requestedUserId = 1) AS c1
, (select count(*) from requests where requesterUserId = 2) AS c2
) v
SET t.requestsRecd = IF(t.userId=1, v.c1 ,t.reqestsRecd)
, t.requestsSent = IF(t.userId=2, v.c2 ,t.reqestsSent)
WHERE t.userId IN (1,2)
由于内联视图返回单行,因此WHERE子句中不需要任何ON子句或谓词。 (*我通常在这里包含CROSS关键字,但它可以在不影响语句的情况下被省略。我包含CROSS关键字的主要理由是让未来的读者明白这个意图,他可能会因为省略连接谓词而感到困惑,期望在ON或WHERE子句中找到一些.CROSS关键字提醒读者有意省略连接谓词。)
另请注意,即使我们在WHERE子句中省略了谓词,语句也会一样,我们可以遍历整个表中的所有行,只有userId = 1或userId = 2的行会受到影响。 (但我们想要包含WHERE子句,以提高性能;我们没有理由获取我们不想修改的行的锁。)
因此,总结一下:是的, 可以在单个语句中执行两个(或更多)行的条件更新。至于您是否要使用此表单,或使用两个单独的语句,由您决定。
答案 1 :(得分:1)
你要做的是两个更新尝试拆分这些:
update user_stats set
requestsRecd = (select count(*) from requests where requestedUserId = 1) where userId = 1;
update user_stats set
requestsSent = (select count(*) from requests where requesterUserId = 2) where userId = 2;
可能有一种使用CASE语句动态选择列的方法,但我不确定这是否可行。
答案 2 :(得分:0)
您正尝试同时更新两个不同的行。这是不可能的。然后使用两个更新查询。
update user_stats set
requestsRecd = (select count(*) from requests where requestedUserId = 1) where userId = 1;
和
update user_stats set
requestsSent = (select count(*) from requests where requesterUserId = 2) where userId = 2;
告诉我这是否有效。