簡體   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