mysql 如何在公用表表达式中实施条件

6rqinv9w  于 2023-02-11  发布在  Mysql
关注(0)|答案(1)|浏览(101)

我们有很多复杂的函数会根据传递的JSON过滤器设置返回列表。问题是,即使一个标志被设置为false,MySQL也会在SELECT语句中执行SQL(使用EXPLAIN)。我不知道如何解决这个问题。例如:

WITH cte1 AS
(
    SELECT pm.ID
    FROM person_main pm
),
cte2 AS
(
    SELECT IF
    (
        @p_filter_job_state_array IS NULL,
        (
            SELECT NULL
        ),
        (
            SELECT sis.ID
            FROM cte1 sis
            INNER JOIN external_link el ON el.ref_id = sis.ID
            WHERE el.headline_value LIKE '%test%'
        )
    ) AS ID
)
SELECT * FROM cte2;

即使@p_filter_job_state_array为NULL,引擎仍在执行SELECT连接external_link。我们有几十个“前端加载”CTE执行此操作,随着过滤器数量的增长,即使我们没有设置过滤器,执行时间也是原来的两倍和三倍(因为引擎正在执行SELECT语句,而我以为它会根据NULL值忽略这些语句)。我需要弄清楚如何使用CTE编写单个查询,并指示编译器避免基于变量设置执行CTE SELECT语句......这可能吗?如果可能,我该怎么做?
另一个重要的例子是因为我们做了大量的前置加载和过滤,有时调用者只想要一个索引数组而不是整个结构,所以我们有这样的东西:

SELECT IF
    (
        p_array_only,
        (
            SELECT JSON_ARRAYAGG(jm.ID)
            FROM 
            (            
                SELECT fs.ID
                FROM  final_sort fs
                LIMIT var_offset, var_rowcount
            ) jm
        ),
        (
            SELECT JSON_OBJECT
            (
                'data', 
                (
                    SELECT JSON_ARRAYAGG(JSON_OBJECT
                    (
                        'data_main', get_json_data_main_list(jm.ID)  
                    ))
                    FROM 
                    (            
                        SELECT fs.ID
                        FROM  final_sort fs
                        LIMIT var_offset, var_rowcount
                    ) jm
                )
            )
        )
    )

当然,问题是如果他们只需要数组,MySQL仍然执行代码的其他部分。是的,我可以把它分成两个单独的SQL语句,但它们使用100%相同的代码“前加载”,所以效率很低。但这是主要问题;我们有一组非常特殊的过滤器需要处理,但我们也需要跳过过滤器,并专注于基于变量设置输出不同的结构。

bvjxkvbb

bvjxkvbb1#

不幸的是,社区没有任何React;预处理语句可能是最好的解决方案(而且工作良好),但正如许多人所知,它将管理复杂代码变成了意大利面条,这可能会非常令人沮丧。

相关问题