繁体   English   中英

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

[英]How do I subtract two declared variables in MYSQL

我正在研究的问题如下:

与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,请帮助。 谢谢

我无法测试此数据,因为我没有您的表格,但是请尝试如下操作:

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

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

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

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

在SQL语句中减去它们

SELECT @foo - @bar AS diff

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

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

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

SELECT @foo := '123.45' ; 

在OP查询中,没有完成分配。 等号是标量值与子查询返回值的比较。 那些第一条语句是否在实际运行中而不会引发错误?

用户定义的变量可能对于解决此问题不是必需的。

您要返回多少行? 听起来您每个月要一个。 我们假设“年份”是指日历年,例如1月到12月。 (我们可能想检查一下这个假设。只是为了避免太晚才发现,这意味着从7月到6月的“财政年度”之类的东西。)

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

问题是……“收款额有什么区别……”

所以,我们希望收到的款项。 那就是我们收到的付款额吗? 还是我们收到的订单数量? (我们是在接受订单并接收付款吗?还是在下订单并进行付款?)

当我想到“收到的金额”时,我在考虑收入。

鉴于我们只看到两个表格,我想我们正在填写订单并收到付款。 (我可能想检查一下,所以完成后,不会告诉我……“哦,我们的意思是收到的订单数量”和/或“付款表是我们已付款的金额,我们收到的金额在其他表格中”

我们将假设有一列标识接收付款的“日期”,并且该列的数据类型为DATE(或DATETIME或TIMESTAMP),我们可以可靠地确定该日期的“月”已收到付款。

为了获得我们在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)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM