我正在处理的问题如下:
与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请帮助。感谢
答案 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)
如果这是一个家庭作业问题,我强烈建议您自己解决这个问题。还有其他查询模式将返回等效结果。