如何将带有子查询的MySQL select语句转换为update语句?
我有下面的工作select语句如何将带有子查询的MySQL select语句转换为update语句?,mysql,sql,sql-update,subquery,Mysql,Sql,Sql Update,Subquery,我有下面的工作select语句 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 表结构如下所示: | tbl
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 |
update语句的结果应该是:
| tblfoo |
+----+------------+--------------+
| id | option_key | option_value |
+----+------------+--------------+
| 1 | foo | value1 |
| 2 | bar | value2 |
| 3 | baz | value3 |
我想用tblfoo
更新option\u值,使用tblbar
中的content
中的相关数据。不幸的是,tblbar
可能有多个具有相同值的refid
条目。这就是为什么子查询需要LIMIT 1
(或groupby t,id
或DISTINCT
)
我发现,当我使用LIMIT 1
进行子查询时,查询速度明显加快,而不是使用SELECT DISTINCT
进行子查询,或者使用groupby t1.id
进行连接。所以在执行时间优化之后,我使用上面的select语句结束了
源表还有一个catch,应该更新它<代码>选项_值
是一个实际字段,它也存在于源表中(但具有NULL
值)
我在尝试将上面的优化select语句转换为update语句时遇到的问题主要是我无法从子查询内部访问t1.id
如何在不丢失性能优化的情况下将select语句转换为update语句?可以通过避免两个表之间的
左连接来进一步优化相关子查询。相反,您可以直接从第二个表中获取内容
值
要进行更新,您可以使用选择查询作为派生表,并将其连接到源表:
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 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;
只需将更新联接与在tblbar
中查找不同值的子查询一起使用即可:
UPDATE tblfoo f
INNER JOIN
(
SELECT DISTINCT refid, content
FROM tblbar
) b
ON f.id = b.refid
SET f.option_value = b.content;
只需将更新联接与在tblbar
中查找不同值的子查询一起使用即可:
UPDATE tblfoo f
INNER JOIN
(
SELECT DISTINCT refid, content
FROM tblbar
) b
ON f.id = b.refid
SET f.option_value = b.content;
如果要更新所有行,则最有效的方法可能是:
UPDATE tblfoo f
SET f.option_value = (SELECT b.content FROM tblbar WHERE f.id = b.refid LIMIT 1);
特别是,这可以利用tblbar(refid,content)
上的索引,如果要更新所有行,那么最有效的方法可能是:
UPDATE tblfoo f
SET f.option_value = (SELECT b.content FROM tblbar WHERE f.id = b.refid LIMIT 1);
特别是,这可以利用tblbar(refid,content)
上的索引来更新哪些表/列和哪些数据?在子查询中,为什么要联接表2和表3;我相信您可以直接使用Table3来显示您正在尝试的代码update@TimBiegeleisen我已经用表结构和更清晰的说明编辑了我的问题,哪些字段应该更新。如果有重复的值,您想使用哪个值?哪些表/列正在用哪些数据更新?在子查询中,为什么加入表2和表3;我相信您可以直接使用Table3来显示您正在尝试的代码update@TimBiegeleisen我已经用表格结构和更清晰的说明编辑了我的问题,哪些字段应该更新。如果有重复的值,您想使用哪一个?谢谢,您的SQL可以工作,但有一个改动:它是设置f.content=b.option\u值代码>。你能更新你的答案吗?那么我可以接受了:)@burnersk事实上,从你给我们看的表格来看,我的答案似乎是正确的。如果没有,请更新您的问题。对不起,您是正确的。我必须匿名的公司限制让我快死了。谢谢你,你的SQL有效,但有一个改动:它是SET f.content=b.option\u value代码>。你能更新你的答案吗?那么我可以接受了:)@burnersk事实上,从你给我们看的表格来看,我的答案似乎是正确的。如果没有,请更新您的问题。对不起,您是正确的。我必须匿名的公司限制让我快死了。你的更新声明有效。然而,@TimBiegeleisen的版本运行速度更快(1分钟比10分钟)@burnersk-yeah-Tim进一步优化。我没有整体优化您的原始查询;只有子查询部分。update语句可以工作。然而,@TimBiegeleisen的版本运行速度更快(1分钟比10分钟)@burnersk-yeah-Tim进一步优化。我没有整体优化您的原始查询;只是子查询部分。