如何在MYSQL中减去两个声明的变量

时间:2016-04-21 03:24:06

标签: mysql sql

我正在处理的问题如下:

与2003年相比,2004年每个月收到的金额有何不同?

这是我到目前为止所拥有的,

    SELECT @2003 = (SELECT sum(amount) FROM Payments, Orders
                WHERE YEAR(orderDate) = 2003
                AND Payments.customerNumber = Orders.customerNumber
                    GROUP BY MONTH(orderDate));

    SELECT @2004 = (SELECT sum(amount) FROM Payments, Orders
                WHERE YEAR(orderDate) = 2004
                AND Payments.customerNumber = Orders.customerNumber
                    GROUP BY MONTH(orderDate));

    SELECT MONTH(orderDate), (@2004 - @2003) AS Diff 
           FROM Payments, Orders
              WHERE Orders.customerNumber = Payments.customerNumber
                 Group By MONTH(orderDate);

在输出中我得到了几个月但是对于Diff我得到NULL请帮助。感谢

3 个答案:

答案 0 :(得分:1)

我无法测试这个,因为我没有你的桌子,但尝试这样的事情:

SELECT a.orderMonth, (a.orderTotal - b.orderTotal ) AS Diff 
FROM 
    (SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal 
    FROM Payments, Orders
    WHERE YEAR(orderDate) = 2004
    AND Payments.customerNumber = Orders.customerNumber
        GROUP BY MONTH(orderDate)) as a,
   (SELECT MONTH(orderDate) as orderMonth,sum(amount) as orderTotal FROM Payments, Orders
    WHERE YEAR(orderDate) = 2003
    AND Payments.customerNumber = Orders.customerNumber
        GROUP BY MONTH(orderDate)) as b
WHERE a.orderMonth=b.orderMonth

答案 1 :(得分:0)

我认为这是问题:
在@ 2003和@ 2004中,您只选择总和。即使您按月分组,您仍然会选择一列,即每行不会说明它所选择的月份。因此,当您尝试减去SQL时,应该从@ 2004中减去@ 2003中的哪一行 所以我认为解决方案是选择带总和的月份,然后根据月份进行减法。

答案 2 :(得分:0)

问:如何在MySQL中减去两个声明的变量。

答:你首先必须要解除它们。在MySQL存储程序的上下文中。但是这些变量名称不会以符号字符开头。以符号 @ 字符开头的变量名称是用户定义的变量。并且没有针对它们的DECLARE语句,我们无法将它们声明为特定类型。

在SQL语句中减去它们

SELECT @foo - @bar AS diff

请注意,MySQL用户定义的变量是标量值。

使用Pascal样式赋值运算符:= 完成在SELECT语句中为用户定义的变量赋值。在SELECT语句的表达式中,等号是一个相等比较运算符。

作为如何在SQL SELECT语句中分配值的简单示例

SELECT @foo := '123.45' ; 

在OP查询中,没有完成任务。等号是标量值与子查询返回值的比较。那些第一个语句是否实际运行而没有抛出错误?

用户定义的变量可能不是解决此问题的必要条件。

你想要返回多少行?听起来你每个月都想要一个。我们假设在&#34;年&#34;我们指的是日历年,如1月到12月。 (我们可能想要检查一下这个假设。只是因为我们没有找到太晚的方法,那就是“财政年度&#34;”,从7月到6月,或其他什么。)< / p>

我们如何获得月份清单?看起来你已经有了一个开始。我们可以使用GROUP BY或DISTINCT。

问题是......&#34; 收到的金额有多大差异 ...&#34;

因此,我们希望收到金额。那是我们收到的付款的金额吗?或者我们收到的订单数量? (我们接受订单和接收付款吗?或者我们发出订单并进行付款?)

当我想到收到的金额&#34;时,我正在考虑收入。

鉴于我们看到的只有两个表,我认为我们正在填写订单并接收付款。 (我可能想检查一下,所以当我完成时,我没有被告知......&#34;哦,我们的意思是我们收到的订单数量&#34;和/或&#34 ;付款表是我们付款的,我们收到的金额是在其他表格中#34;

我们假设有一个列标识了&#34; date&#34;收到付款,并且该列的数据类型是DATE(或DATETIME或TIMESTAMP),某种类型我们可以可靠地确定什么&#34;月&#34;已收到付款。

要获取我们在2003年收到付款的月份清单......

 SELECT MONTH(p.payment_received_date)
   FROM payment_received p
  WHERE p.payment_received_date >= '2003-01-01'
    AND p.payment_received_date <  '2004-01-01'
  GROUP BY MONTH(p.payment_received_date)
  ORDER BY MONTH(p.payment_received_date)

那应该给我们十二排。除非我们在一个月内没有收到任何付款。然后我们可能只得到11行。或者10.或者,如果我们在2003年没有收到任何付款,我们就不会获得任何行。

为了提高性能,我们希望得到我们的谓词(WHERE子句中的条件引用裸列。使用适当的索引,MySQL将有效地使用索引范围扫描操作。如果我们将列包装在函数中,例如

  WHERE YEAR(p.payment_received_date) = 2003 

有了这个,我们将强制MySQL在表中的每个翻转行上评估该函数,然后将函数的返回值与文字进行比较。我们不希望这样做,并在谓词中引用裸列(WHERE子句中的条件)。

我们可以重复相同的查询来获得2004年收到的付款。我们需要做的就是更改日期文字。

或者,我们可以将2003年和2004年的所有行放在一起,然后将其折叠成不同月份的列表。

我们可以使用条件聚合。由于我们使用日历年,我将使用YEAR()快捷方式(而不是范围检查)。在这里,我们并不关心在表达式中使用裸列。

SELECT MONTH(p.payment_received_date) AS `mm`
     , MAX(MONTHNAME(p.payment_received_date)) AS `month`
     , SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0)) AS `2004_month_total`
     , SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2003_month_total`
     , SUM(IF(YEAR(p.payment_received_date)=2004,p.payment_amount,0))
     - SUM(IF(YEAR(p.payment_received_date)=2003,p.payment_amount,0)) AS `2004_2003_diff`
  FROM payment_received p
 WHERE p.payment_received_date >= '2003-01-01'
   AND p.payment_received_date <  '2005-01-01'
 GROUP
    BY MONTH(p.payment_received_date)
 ORDER
    BY MONTH(p.payment_received_date)

如果这是一个家庭作业问题,我强烈建议您自己解决这个问题。还有其他查询模式将返回等效结果。