撤消cte(公共表表达式)

tuwxkamq  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(246)

另一个开发人员针对mariadb(mysql版本10.x)编写了一个查询,而不是mysql数据库(mysql版本5.6)。他们不再可以让他们重写MySQL5.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;

表和列已更改以保护无辜者。

2izufjch

2izufjch1#

“easy button”修复方法是采用cte的定义,并将其用作内联视图,以代替对的引用 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 无效,因为没有名为的列 actiontemptable .)
然后替换对cte的引用 temptable 使用内联视图定义。
在查询中,这将是aliaas 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

编辑
哦,还有。。。引用 :var1 以及 :var2 第二次出现的内联视图定义中的占位符可能需要更改为唯一的。。。 :var1b 以及 :var2b (至少,使用pdo的命名占位符是这种情况,它们必须是唯一的)
提供的值的副本 :var1 以及 :var2 需要为新的绑定占位符提供。
后续行动
问:这个查询是。。。打了很多。你提到一个“简单的解决方案”,但代价是什么?
答:在“easy button”修复程序中,两个内联视图 a 以及 q (替换cte参考)正在单独实现。内联视图查询执行两次,结果具体化为两个独立的派生表(explain输出将显示两个独立的派生表, a 以及 q ).

相关问题