[英]How to convert a MySQL select statement with a subquery to the same table into an update statement?
我有以下工作选择语句。
SELECT t1.id, t1.option_key, (
SELECT
t3.content AS option_value
FROM tblfoo t2
LEFT OUTER JOIN tblbar t3 ON( t3.refid = t2.id )
WHERE t2.id = t1.id
LIMIT 1
) AS option_value
FROM tblfoo t1
表结构如下所示:
| tblfoo |
+----+------------+--------------+
| id | option_key | option_value |
+----+------------+--------------+
| 1 | foo | NULL |
| 2 | bar | NULL |
| 3 | baz | NULL |
| tblbar |
+----+-----------------+
| id | refid | content |
+----+-----------------+
| 1 | 1 | value1 |
| 1 | 2 | value2 |
| 1 | 3 | value3 |
更新语句的结果应为:
| tblfoo |
+----+------------+--------------+
| id | option_key | option_value |
+----+------------+--------------+
| 1 | foo | value1 |
| 2 | bar | value2 |
| 3 | baz | value3 |
我想更新option_value
与tblfoo
从相关的数据content
从tblbar
。 不幸的是, tblbar
可能有多个具有相同值的refid
条目。 这就是为什么子查询需要LIMIT 1
(或GROUP BY t,id
或DISTINCT
)的原因。
我已经知道,当我使用LIMIT 1
进行子查询而不是使用SELECT DISTINCT
或与GROUP BY t1.id
组合的GROUP BY t1.id
进行子查询时,查询速度显着提高。 因此,在执行时间优化之后,我得到了上面的select语句。
源表还有一个问题,应该进行更新。 option_value
是一个实际字段,也存在于源表中(但具有NULL
值)。
尝试将上面的优化选择语句转换为更新语句时遇到的问题主要是我无法从子查询内部访问t1.id
如何在不损失性能优化的情况下将select语句转换为update语句?
只需tblbar
查询使用update join即可在tblbar
找到不同的值:
UPDATE tblfoo f
INNER JOIN
(
SELECT DISTINCT refid, content
FROM tblbar
) b
ON f.id = b.refid
SET f.option_value = b.content;
通过避免两个表之间的Left Join
,可以进一步优化您的相关子查询。 相反,您可以直接从第二个表中获取content
值。
要进行更新,可以将select
查询用作派生表,并将其联接到源表:
UPDATE tblfoo AS tfoo
JOIN (
SELECT t1.id,
(SELECT t3.content AS option_value
FROM tblbar t3
WHERE t3.refid = t1.id
LIMIT 1
) AS option_value
FROM tblfoo t1
) AS dt ON dt.id = tfoo.id
SET tfoo.option_value = dt.option_value;
如果要更新所有行,则最有效的方法可能是:
UPDATE tblfoo f
SET f.option_value = (SELECT b.content FROM tblbar WHERE f.id = b.refid LIMIT 1);
特别是,这可以利用tblbar(refid, content)
上的索引。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.