Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql SQL SELECT语句表达式值对其他表达式的重用_Mysql_Sql_Sql Server - Fatal编程技术网

Mysql SQL SELECT语句表达式值对其他表达式的重用

Mysql SQL SELECT语句表达式值对其他表达式的重用,mysql,sql,sql-server,Mysql,Sql,Sql Server,我在mysql中有一个行数巨大的表(尽管我正在寻找通用的SQL解决方案) 我想要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 只要表达式1简单,它看起来就很好且易于阅读。 但是当CASE-when/IFNULL

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

我想要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
只要表达式1简单,它看起来就很好且易于阅读。
但是当CASE-when/IFNULL()/SUM()/MIN()/STRCAT()或某些运算符在这些表达式中起作用时,很难读取和调试

我已经讨论了一些已经提出的问题


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

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
这可以很好地工作,但执行此查询要多花70倍的时间。至少在我发射它的时候,虽然只有一次。
如果输出列中有多个级别的表达式,该怎么办

有什么优雅的方法可以在不影响可读性的情况下处理这个问题吗


顺便问一下,为什么SQL标准或供应商不支持select语句中的表达式重用或别名引用?(假设在单个SELECT语句表达式中没有循环求值。在这种情况下,编译器会失败)

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

那么您的查询将如下所示

select a
, myfunction( b, c)
, myfunction( b, c) + a
...
好处-这将清除“选择代码”,这是您声明的目标,您还可以集中管理更复杂的逻辑


缺点-这不是将移植到其他系统的“通用sql”,如果功能很少被重复使用,可能不值得在时间上进行投资

将实际查询用作子查询

 select a,exp1,exp1+a as exp2
 from (SELECT a 
             ,(b + c) as exp1
       FROM very_big_table
       WHERE ...
       GROUP BY a
 )V
 ORDER BY a DESC
或者为查询添加外部应用语句

SELECT a 
      ,OA.exp1 as expression1
      ,(OA.exp1 + a) AS expression2 -- basically (expression1 + a)
FROM very_big_table
outer apply (select (b + c) as exp1) OA
WHERE ...
GROUP BY a
ORDER BY a DESC
我想第二个选项,使用外部应用,更适合阅读

请记住,每行都会运行外部应用程序

因此,如果exp1必须从表中访问大量数据,这可能是个坏主意

无论如何,只要使用您在实际查询中已经得到的字段即可 添加它不会有很大的成本


所以。。您将选择什么方式?

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

SELECT a, 
    @expr1 := (b + c) as expression1,
    (@expr1 + a) AS expression2
FROM very_big_table
WHERE ...
GROUP BY a
ORDER BY a DESC
Postgresql用户可参考。

如果您想最大限度地提高复杂计算和/或逻辑的可读性,请将计算封装在它自己的函数中

create table x
(
    a int not null,
    b int not null,
    c int not null
);

create table y
(
    a int not null,
    z int not null
);


select * from x;

insert into x VALUES
(1,2,3), (4,5,6);

insert into y values
(1, 100);
具有复杂计算和/或逻辑的功能: 测试查询:

select x.a, x.b, x.c, y.z, answer.*
from x
join y on x.a = y.a
cross join lateral computer(x,y) answer 
with data_source as
(
    select x.*, y.z
    from x
    join y on x.a = y.a
)
select ds.*, answer.*
from data_source ds
cross join lateral computer_b(ds) answer
输出:

如果您只需要快速测试函数的返回值,可以使用括号星号语法对其进行扩展:

select x.a, x.b, x.c, y.z, (computer(x, y)).*
from x
join y on x.a = y.a
但是不要在生产中使用它,如果函数有50个返回列,那么函数将被调用50次。在生产中使用横向交叉连接。见:

如果函数本身不需要考虑数据源的来源,只需使用函数参数上的
记录
类型即可

create or replace function computer_b
(
    anon record,
    out expression1 int, out expression2 int, out expression3 int
)
as $$
begin
    expression1 := anon.b + anon.c;
    expression2 := expression1 + anon.a;
    expression3 := expression2 + anon.z;
end;
$$ language 'plpgsql';  
测试查询:

select x.a, x.b, x.c, y.z, answer.*
from x
join y on x.a = y.a
cross join lateral computer(x,y) answer 
with data_source as
(
    select x.*, y.z
    from x
    join y on x.a = y.a
)
select ds.*, answer.*
from data_source ds
cross join lateral computer_b(ds) answer

为什么您认为能够重用表达式别名将导致执行时间减少70倍?您能展示一个实际执行计划的实际查询和.sqlplan文件的实例吗?我几乎可以保证,执行时间上的这种差异不是由于添加了子查询造成的——其他的东西肯定不同。@Quail仍然无法想象这样一种情况,即这是唯一的差异,它会导致70倍的性能差异。我在Aaron编辑完他的评论后删除了我的评论。对于后人来说,它说,“我想他是在比较它,明确地指定每一列。”至于为什么,让我们不要重新散列:这个非常大的表有主键吗?它是什么?为什么
外部应用
而不是
交叉应用