SQL SELECT语句表达式值重用于其他表达式

use*_*953 6 mysql sql sql-server

我有一个在mysql中有大量行数的表(虽然我正在寻找通用的SQL解决方案)

very_big_table(INT a, INT b, INT c, ...)
Run Code Online (Sandbox Code Playgroud)

我想要SELECT语句

SELECT a, 
    (b + c) as expression1,
    (b + c + a) AS expression2 -- basically (expression1 + a)
FROM very_big_table
WHERE ...
GROUP BY a
ORDER BY a DESC
Run Code Online (Sandbox Code Playgroud)

只要表达式1很简单,这看起来很好并且易于阅读.
但是当CASE-WHEN/IFNULL()/ SUM()/ MIN()/ STRCAT()或某些运算符在这些表达式中起作用时,它很难读取和调试.

我已经完成了一些已经问过的问题,
将mysql值分配给变量内联
使用另一列的列值(SQL Server)?
如何在同一个select语句中使用条件列值?

但是,如果我使用描述的方法

SELECT a, 
    expression1,
    (expression1 + a) AS expression2
FROM 
    (SELECT a,
        (b + c) AS expression1
    FROM very_big_table
    WHERE ...
    GROUP BY a) as inner_table
ORDER BY a DESC
Run Code Online (Sandbox Code Playgroud)

这工作正常,但这个查询需要花费大约70倍的时间来执行.至少只有一次,我解雇了它.
如果我在输出列中有多个级别的表达式怎么办?

有没有优雅的方法来处理这个问题,而不影响可读性?

BTW为什么在SQL标准或供应商不支持的select语句中,这个表达式是否重用别名引用?(假设在单个SELECT语句表达式中没有循环评估.在这种情况下编译器失败)

Hen*_*Luo 5

您可以使用用户定义的变量来解决您的问题。您的SQL可以重写为:

SELECT a, 
    @expr1 := (b + c) as expression1,
    (@expr1 + a) AS expression2
FROM very_big_table
WHERE ...
GROUP BY a
ORDER BY a DESC
Run Code Online (Sandbox Code Playgroud)

您可以参考这篇文章


spi*_*ter 0

解决方法假设表达式不是 sql select 子子句,而是纯粹作用于原始“select from”子句中检索的数据的嵌套运算符/函数,因此手头的任务纯粹是为了使代码“看起来很漂亮”:创建用户定义的函数

那么你的查询看起来像

select a
, myfunction( b, c)
, myfunction( b, c) + a
...
Run Code Online (Sandbox Code Playgroud)

好处 - 这会清理您既定目标的“选择代码”,您也可以集中管理更复杂的逻辑

缺点 - 这不是可以移植到其他系统的“通用 SQL”,如果这些功能很少被重用,那么可能不值得及时投资