在同一查询中重用计算字段

reuse a calculated field in the same query

我有这个问题。

SELECT carte.nome, sum(amount) AS total, (1500-sum(amount)) AS residuo 
FROM movimenti_carta JOIN carte ON movimenti_carta.banca=carte.id 
WHERE data BETWEEN '2019-05-01' AND '2019-05-31' 
GROUP by banca

这个查询的目标是在一段时间内求和一些金额(sum(amount))。我还将此金额的下限设置为 1500,因此我想在第三个字段中进行计算。我试着做

SELECT carte.nome, sum(amount) AS total, (1500-total) AS residuo 
FROM movimenti_carta JOIN carte ON movimenti_carta.banca=carte.id 
WHERE data BETWEEN '2019-05-01' AND '2019-05-31' 
GROUP by banca

但 mysql 抱怨 totale 不是已知字段(它是派生字段)。 第一个查询有效,但效率不高。我缺少什么才能让第二个工作?

Mysql 不支持使用变量,除非它在 ​​HAVING 语句中,因此要使其工作,您应该将其重写为

SELECT carte.nome, sum(amount) AS total, (1500-sum(amount)) AS residuo 
FROM movimenti_carta JOIN carte ON movimenti_carta.banca=carte.id 
WHERE data BETWEEN '2019-05-01' AND '2019-05-31' 
GROUP by banca

您可以使用通用 Table 表达式 (CTE):

WITH cte_query AS (
SELECT carte.nome AS nome, sum(amount) AS total
FROM movimenti_carta JOIN carte ON movimenti_carta.banca=carte.id 
WHERE data BETWEEN '2019-05-01' AND '2019-05-31' 
GROUP by banca
)

SELECT nome, total, (1500- total) AS residuo 
FROM cte_query

子查询也可以:

SELECT nome, total, (1500- total) AS residuo 
FROM (
SELECT carte.nome AS nome, sum(amount) AS total
FROM movimenti_carta JOIN carte ON movimenti_carta.banca=carte.id 
WHERE data BETWEEN '2019-05-01' AND '2019-05-31' 
GROUP by banca
) A

你可以改正为

SELECT 
nome ,
total,
 residuo AS residuo_TMP,
 (1500-total) AS residuo 
 FROM 
 (SELECT 
carte.nome,
SUM(amount) AS total,
(1500- SUM(amount)) AS residuo 
 FROM
movimenti_carta 
JOIN carte 
  ON movimenti_carta.banca = carte.id 
 WHERE DATA BETWEEN '2019-05-01' 
AND '2019-05-31' 
GROUP BY banca ) aa

列别名不能在定义它们的 SELECT 中 re-used -- 原因很简单。 MySQL(特别是)和 SQL 通常不保证 SELECT.

中表达式的求值顺序

对于您的情况,最简单的解决方案是重复表达式,因为它是如此简单。

不过,您的查询还有另一个问题。您正在按 banca 聚合,但仅选择 nome.

下面是编写查询的更好方法:

SELECT c.nome, sum(?.amount) AS total,
       (1500 - sum(?.amount)) AS residuo 
FROM movimenti_carta mc JOIN
     carte c
     ON mc.banca = c.id 
WHERE ?.data >= '2019-05-01' AND
      ?.data < '2019-06-01' 
GROUP by c.nome;

注意变化:

  • 所有列引用都应该是合格的。 ? 是列来源的 table 的别名。
  • 使用 table 别名,它们是 table 名称的缩写。
  • SELECT 中的未聚合列在 GROUP BY 中。
  • 日期算法适用于日期和 date/time 值。