我可以在SELECT查询中重用计算字段吗?


78

有没有一种方法可以重用mysql语句中的计算字段。我收到以下错误信息:“ unknown column total_sale”:

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / total_sale as f1_percent
FROM sales s

还是我必须重复计算,如果我添加了所有需要的计算,这将导致很长的SQL语句。

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / (s.f1 + s.f2) as f1_percent
FROM sales s

当然,我可以在我的php程序中进行所有计算。


“当然,我可以在php程序中进行所有计算”-那不是最糟糕的主意。
Paul Spiegel

Answers:


83

是的,您可以重用变量。这是您的操作方式:

SELECT 
    @total_sale := s.f1 + s.f2 as total_sale, 
    s.f1 / @total_sale as f1_percent
FROM sales s

在这里阅读更多有关它的信息:http : //dev.mysql.com/doc/refman/5.0/en/user-variables.html

[注意:此行为是不确定的。根据MySQL文档:]

通常,永远不要为用户变量分配值,并且不要在同一条语句中读取该值。您可能会得到期望的结果,但这不能保证。


@OMG Ponies介意吗?“ @total_sale:=”声明不够吗?
rzetterberg

那是设置变量,而不是声明它。声明意味着使用SET语句或派生表/内联视图。
OMG小马

2
“还可以在SET以外的语句中为用户变量分配值。在这种情况下,赋值运算符必须为:=而不是=,因为在非SET语句中后者被视为比较运算符=:”
rzetterberg

13
@OMGPonies(及其他):不支持此操作:“通常,永远不要为用户变量分配值,也不要在同一条语句中读取该值。您可能会得到期望的结果,但这不能保证。” 它可以正常运行。但是结果可能不正确。
阿里尔(Ariel)

3
当我尝试将其与组函数一起使用时(例如SUMCOUNT,我得到了违反直觉且无济于事的结果,即变量始终具有上一行的值,而不是我所在行的值。这是有充分理由不支持的,应该是避免。
戴维·莫尔斯

64

以下内容在我对MySQL 5.5的测试中似乎运作良好:

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / (SELECT total_sale) as f1_percent
FROM sales s

5
我喜欢这个。到目前为止,所有答案的可读性都最好,并且在mysql文档中没有关于使用它的警告。但是,它不能用于引用组结果,例如通过SUM或COUNT获得的结果。
大卫

3
由于当前接受的答案并非每次都能奏效,因此这才是被接受的答案
Robin Choffardet

1
我刚刚使用以下代码在MariaDB 10.1.24上进行了测试,并且运行良好。从项目数限制100中选择SELECT Price_Per_SqFt,(Price_Per_SqFt / 2)AS col1,(SELECT col1 + 1)AS col2
罗伯特·D

4
请注意,这可能仅适用于简单的算术运算,但不适用于egSUMCOUNT:您将得到reference '[colname]' not supported (reference to group function)
David Moles

如果您选择的列名与任何表(从表或联接表)上的另一个实际列共享该名称,这似乎也不起作用
Brian Leishman

14

仅跨平台支持的方法是使用派生表/内联视图:

SELECT x.total_sale,
       x.f1 / x.total_sale as f1_percent
  FROM (SELECT s.f1,
               s.f1 + s.f2 as total_sale, 
          FROM sales s) x

8

您可以使用子选择:

select tbl1.total_sale,
       tbl1.f1/tbl1.total_sale as f1_percent 
  from (select s.f1+s.f2 AS total_sale, 
               s.f1 
          from sales s) as tbl1;

5

您可以使用子查询,如下所示:

SELECT 
    h.total_sale, 
    s.f1 / h.total_sale AS f1_percent
FROM sales s,
    (SELECT id, f1 + f2 AS total_sale FROM sales) h
WHERE
    s.id = h.id

编辑:
固定笛卡尔积,假设主键为id
经过优化后,这应该等效于OMG Ponies的解决方案,但是我认为如果您需要更多的子查询,它将变得更加难以阅读。


2

我在这里查看了各种答案,并做了一些实验。

具体来说,我正在使用MariaDB 10.1。

对于“简单”的事情,您可以执行罗伯特·D(Robert D)在其评论中建议的操作:

SELECT Price_Per_SqFt, (Price_Per_SqFt/2) AS col1, (SELECT col1 + 1) AS col2 FROM Items 

如果您将某种聚合函数与内部联接一起使用,则不能使用此方法,但是可以将此方法与内部联接方法结合使用,如下所示(NB VAT =“营业税” ...和NB以财务数据货币表示)字段通常有4个小数位,我认为这是有历史意义的...)

SELECT 
    invoices.invoiceNo, invoices.clientID, invoices.Date, invoices.Paid, 
  invoicesWithSubtotal.Subtotal,
  ROUND( CAST( Subtotal * invoices.VATRate AS DECIMAL( 10, 4 )), 2 ) AS VAT,
  (SELECT VAT + Subtotal) AS Total
FROM invoices 
    INNER JOIN 
    ( SELECT Sum( invoiceitems.Charge ) AS Subtotal, invoices.InvoiceNo FROM invoices 
        INNER JOIN invoiceitems ON invoices.InvoiceNo = invoiceitems.InvoiceNo
            GROUP BY invoices.InvoiceNo ) invoicesWithSubtotal
    ON invoices.InvoiceNo = invoicesWithSubtotal.InvoiceNo

我想使用上面的方法创建一个View清单,以列出发票的小计,增值税和总计...事实证明,MariaDB(几乎可以肯定是MySQL)不允许在FROM子句中嵌套。但是,通过使第View一个列出InvoiceNoand Subtotal,然后使第二个View引用第一个,可以轻松解决此问题。在性能方面,我完全不知道这种双重View安排。


0

我一直在测试以下内容,并且似乎一直都在工作,也许是有原因的,因为我已将变量@total_sales预先定义为值而不是字符串,并且在选择过程中未重新定义其类型声明??

如果我执行以下操作

    set @total_sales = 0;

    SELECT 
       @total_sale := s.f1 + s.f2 as total_sale, 
      s.f1 / @total_sale as f1_percent
   FROM sales s

变量的主要问题不是键入,而是执行顺序。该文档指出:“除了在SET语句中,您永远不要为用户变量分配值,并且在同一条语句中读取该值。您可能会得到预期的结果,但是不能保证(...)顺序涉及用户变量的表达式的求值结果未定义。”。在您的示例中,@ total_sales在计算f1_percent时可能具有正确的值,但也可能具有前一行的值。
Eino Gourdin '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.