Mysql在5.7.x中选择不同的子查询与查询
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql在5.7.x中选择不同的子查询与查询相关的知识,希望对你有一定的参考价值。
让我先说一下,我在这里描述的内容在mysql 5.6.x及更低版本中运行得很好。现在我们尝试更新到mysql 5.7并查找此UPDATE语句的问题。
我们有一个看起来像这样的表:
imagefile
----------
id int
itemId int
...
sequenceNumber int
updatedDate date
在我们的应用程序中,用户必须在Item中重新排序imageFiles。我们这样做的SQL看起来像这样:
UPDATE imageFile f1
JOIN (
SELECT f2.id, (@row:=@row+1) rowNum
FROM imageFile f2, (SELECT @row:=0) dm
WHERE f2.itemId = 8035323
ORDER BY f2.sequenceNumber, f2.updatedDate
) rs ON f1.id = rs.id
SET f1.sequenceNumber = rs.rowNum;
如果我只将select部分作为独立查询运行,它会产生以下结果:
SELECT f2.id, f2.sequenceNumber, sqNum (@row:=@row+1) rowNum, updatedDate
FROM imageFile f2, (SELECT @row:=0) dm
WHERE f2.itemId = 8035323
ORDER BY f2.sequenceNumber, f2.updatedDate;
id sqNum rowNum updatedDate
| 9 | 1 | 1 |2018-04-16 18:39:12
| 8 | 2 | 2 |2018-04-16 18:38:42
| 7 | 3 | 3 |2018-04-16 18:37:03
| 6 | 4 | 4 |2018-04-16 18:37:28
| 5 | 5 | 5 |2018-04-16 18:36:37
| 4 | 6 | 6 |2018-04-16 18:38:16
| 3 | 7 | 7 |2017-09-12 16:59:20
哪个是正确的,正是我所期望的...在我使用SELECT作为子查询/ join运行UPDATE后,我得到了这个:
id sqNum rowNum updatedDate
| 3 | 1 | 1 |2017-09-12 16:59:20
| 4 | 2 | 2 |2018-04-16 18:38:16
| 5 | 3 | 3 |2018-04-16 18:36:37
| 6 | 4 | 4 |2018-04-16 18:37:28
| 7 | 5 | 5 |2018-04-16 18:37:03
| 8 | 6 | 6 |2018-04-16 18:38:42
| 9 | 7 | 7 |2018-04-16 18:39:12
这是完全错误的,似乎没有遵循我告诉它的任何顺序。显然在新版本的mysql中有些变化。当我在每个版本中为该查询执行EXPLAIN时,它也是不同的......
5.6.34
id select_type table type possible keys key key length ref rows extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 35 NULL
1 PRIMARY i1 eq_ref PRIMARY PRIMARY 4 rs.id 1 NULL
2 DERIVED <derived3> system NULL NULL NULL NULL 1 Using filesort
2 DERIVED i2 ref uc_ItemNumber, in_workspaceId uc_ItemNumber 4 const 35 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
5.7.18
id select_type table type possible_keys key key_len ref rows extra
1 PRIMARY <derived2> ALL 35
1 UPDATE i1 eq_ref PRIMARY PRIMARY 4 rs.id 1
2 DERIVED i2 ref uc_ItemNumber, in_workspaceId uc_ItemNumber 4 const 35 Using temporary; Using filesort
2 DERIVED <derived3> ALL 1 Using join buffer (Block Nested Loop)
3 DERIVED No tables used
我的问题是如何让这回到以前/期望的行为?
答案
我似乎记得不应该使用/依赖MySQL DML语句的会话变量。但好消息是我们可以在没有会话变量的情况下重写您的查询:
UPDATE imageFile f1
INNER JOIN
(
SELECT
f2.id,
(SELECT COUNT(*)
FROM imageFile t
WHERE t.itemId = 8035323 AND
(t.sequenceNumber < f2.sequenceNumber OR
t.sequenceNumber = f2.sequenceNumber AND
(t.updatedDate < f2.updatedDate OR
(t.updatedDate = f2.updatedDate AND t.id < f2.id)))) rowNum
FROM imageFile f2
WHERE f2.itemId = 8035323
) rs
ON f1.id = rs.id
SET f1.sequenceNumber = rs.rowNum;
以上是关于Mysql在5.7.x中选择不同的子查询与查询的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 的子查询和left join的比较,啥时候用子查询效率高,啥时候用left join效率高?