[英]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.