另一位开发人员针对 MariaDB(MySQL 版本 10.x)编写了一个查询,而不是应该为 MySQL 数据库(MySQL 版本 5.6)编写的查询。他们不再可以让他们为 MySQL 5.6 重写它。
有人可以协助进行逆向工程吗?
WITH temptable (column1, column2, column3)
AS (SELECT t3.column1,
t3.column2,
CASE
WHEN t3.column3 = 1
AND t2.column3 = 1 THEN 2
ELSE COALESCE(t2.column3, 0)
END AS column3
FROM table1 t1
JOIN table2 t2
ON t1.column5 = t2.column5
AND t1.column6 = t2.column6
JOIN table3 t3
ON t3.column1 = t2.column1
WHERE t1.column4 = :var1
AND t1.column6 = :var2
AND t3.column7 = 0)
SELECT column2,
column3
FROM temptable
UNION
SELECT t3.column2,
t3.column3
FROM table3 t3
WHERE t3.column7 = -1
UNION
SELECT t3.column2,
0 AS column3
FROM table3 t3
LEFT JOIN temptable temp
ON temp.column2 = t3.column2
WHERE temp.action IS NULL
AND t3.column7 = 0;
表格和列已更改以保护无辜者。
最佳答案
“简单按钮”修复是采用 CTE 的定义并将其用作内联 View ,代替外部查询中对 temptable
的引用。 (这不一定是最佳解决方案,也不一定是编写查询的最佳方法。)
切掉查询的开头,这部分,
WITH temptable
( column1
, column2
, column3
)
AS
( SELECT t3.column1
, t3.column2
, CASE
WHEN t3.column3 = 1 AND t2.column3 = 1 THEN 2
ELSE COALESCE(t2.column3, 0)
END AS column3
FROM table1 t1
JOIN table2 t2
ON t1.column5 = t2.column5
AND t1.column6 = t2.column6
JOIN table3 t3
ON t3.column1 = t2.column1
WHERE t1.column4 = :var1
AND t1.column6 = :var2
AND t3.column7 = 0
)
只剩下这个:
SELECT a.column2
, a.column3
FROM temptable a
UNION
SELECT b.column2
, b.column3
FROM table3 b
WHERE b.column7 = -1
UNION
SELECT p.column2
, 0 AS column3
FROM table3 p
LEFT
JOIN temptable q
ON q.column2 = p.column2
WHERE q.action IS NULL
AND p.column7 = 0
(正如对该问题的评论中所述,对 action
的引用无效,因为 temptable
中没有名为 action
的列。 )
然后将对 CTE temptable
的引用替换为内联 View 定义。
在查询中,这将是别名 a
和 q
。
像这样:
SELECT a.column2
, a.column3
FROM -- temptable
(
SELECT t3.column1
, t3.column2
, CASE
WHEN t3.column3 = 1 AND t2.column3 = 1 THEN 2
ELSE COALESCE(t2.column3, 0)
END AS column3
FROM table1 t1
JOIN table2 t2
ON t1.column5 = t2.column5
AND t1.column6 = t2.column6
JOIN table3 t3
ON t3.column1 = t2.column1
WHERE t1.column4 = :var1
AND t1.column6 = :var2
AND t3.column7 = 0
) a
UNION
SELECT b.column2
, b.column3
FROM table3 b
WHERE b.column7 = -1
UNION
SELECT p.column2
, 0 AS column3
FROM table3 p
LEFT
JOIN -- temptable
(
SELECT t3.column1
, t3.column2
, CASE
WHEN t3.column3 = 1 AND t2.column3 = 1 THEN 2
ELSE COALESCE(t2.column3, 0)
END AS column3
FROM table1 t1
JOIN table2 t2
ON t1.column5 = t2.column5
AND t1.column6 = t2.column6
JOIN table3 t3
ON t3.column1 = t2.column1
WHERE t1.column4 = :var1
AND t1.column6 = :var2
AND t3.column7 = 0
) q
ON q.column2 = p.column2
WHERE q.action IS NULL
AND p.column7 = 0
编辑
哦,还有...第二次出现的内联 View 定义中对 :var1
和 :var2
占位符的引用可能需要更改为唯一... :var1b
和 :var2b
(至少,使用 PDO 的命名占位符就是这种情况,它们必须是唯一的)
需要为新的绑定(bind)占位符提供为 :var1
和 :var2
提供的值的副本。
跟进
问:这个查询……点击率很高。您提到了“简单的修复”,但代价是什么?
答:在“简单按钮”修复中,两个内联 View a
和 q
(替换对 CTE 的引用)分别具体化。内联 View 查询执行两次,结果具体化到两个单独的派生表中。 (EXPLAIN 输出将显示两个单独的派生表,a
和 q
)。
关于mysql - 撤消 CTE(公用表表达式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50937740/