【问题标题】:How to emulate a dependent CTE如何模拟依赖 CTE
【发布时间】:2022-06-12 02:36:46
【问题描述】:

从这个问题Possible to emulate a basic CTE in MySQL by in-lining it 跟进,是否可以在不使用 CTE 的情况下在 mysql5.7 中内联以下查询?

WITH tbl1 AS (
    SELECT 1 AS a
), tbl2 AS (
    SELECT 1 AS a UNION ALL SELECT 2
), tbl3 AS (
    SELECT * FROM tbl1 JOIN tbl2 USING (a)
) SELECT * FROM tbl3, tbl2

如果是这样,那怎么做?

【问题讨论】:

  • 如果您的 CTE 中没有非确定性构造,或者如果此类 CTE 使用过一次,则只需将 CTE 名称嵌套地替换为其子查询。如果存在非确定性构造,并且必须多次使用 CTE,则为这些 CTE 临时创建(不是临时!)表是唯一的选择。
  • @Akina 你能否澄清你的意思:then temporarily created (not temporary!) tables for these CTEs is the only option。你将如何为WITH cte AS (SELECT RAND() AS a)... 创建一个临时创建的表?
  • 作为单独的CREATE TABLE .. SELECT 查询。
  • @Akina 当然,但这与 tmp 表有什么不同?无论如何,它会在使用后被销毁,所以我认为这不是问题。
  • 临时表不能在查询中多次使用。

标签: mysql common-table-expression


【解决方案1】:

这样做没有什么特别的问题,只是你必须重复 tbl2:

SELECT *
FROM (
    SELECT *
    FROM (
        SELECT 1 AS a
    ) tbl1
    JOIN (
        SELECT 1 AS a UNION ALL SELECT 2
    ) tbl2
    USING (a)
) tbl3
CROSS JOIN
(
    SELECT 1 AS a UNION ALL SELECT 2
) tbl2

fiddle

【讨论】:

    【解决方案2】:

    这类似于替换函数的主体。以类似的方式编写它(从概念上讲):

    let tbl1 =  (SELECT 1 AS a)                          AS tbl1
    let tbl2 =  (SELECT 1 AS a UNION ALL SELECT 2)       AS tbl2
    let tbl3 =  (SELECT * FROM tbl1 JOIN tbl2 USING (a)) AS tbl3
    -- rewriting tbl1 for tbl1 and tbl2
    let tbl3 =  (SELECT * FROM (SELECT 1 AS a) AS tbl1 
                 JOIN ((SELECT 1 AS a UNION ALL SELECT 2)) AS tbl1 USING (a)) AS tbl3
    
    
    SELECT * FROM tbl3, tbl2
    -- substitutie for tbl3, tbl2
    SELECT * FROM 
        (SELECT * FROM (SELECT 1 AS a) AS tbl1 
                  JOIN ((SELECT 1 AS a UNION ALL SELECT 2)) AS tbl1 USING (a)) AS tbl3,
        (SELECT 1 AS a UNION ALL SELECT 2) AS tbl2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多