2012-11-26 68 views
3

請你幫我找出我是否正確?我是SQL新手,所以有很多事情對我來說並不明顯。獲取給定時間段內分組項目的最新值,零和空值

我們假設我有兩張表。
首先是用戶的列表:

 subscribers 
+--------+------------+ 
|subscID | name | 
+--------+------------+ 
| 123 | SomeName00 | 
| 456 | SomeName01 | 
| 789 | SomeName02 | 
| 012 | SomeName03 | 
| 345 | SomeName04 | 
+--------+------------+ 

而第二個是呼叫日誌(或類似的東西),其中包括用戶的收入與事務ID的支出及其賬戶的當前狀態:

     transactions 
+--------+---------------------+--------+-----------+----------+ 
| trnID | date    |subscID | amount | balance | 
+--------+---------------------+-------+------------+----------+ 
| 321456 | 2012-03-13 11:10:00 | 456 | 70.0000 | 90.0000 | 
| 234567 | 2012-03-16 15:05:00 | 456 | -45.0000 | 45.0000 | 
| 345678 | 2012-03-19 17:27:00 | 456 | 15.0000 | 60.0000 | 
| 654321 | 2012-04-22 17:34:00 | 456 | -10.0000 | 50.0000 | 
|| 2012-04-15 15:45:00 | 789 | 20.0000 | 30.0000 | 
| 567890 | 2012-05-16 13:30:00 | 789 | -10.0000 | 20.0000 | 
| 876543 | 2012-02-29 11:00:00 | 012 | 20.0000 | 5.0000 | 
| 678901 | 2012-03-31 09:40:00 | 012 | 10.0000 | 15.0000 | 
| 456789 | 2012-03-31 21:09:00 | 012 | -13.0000 | 2.0000 | 
|9 | 2012-02-23 14:01:00 | 345 | -30.0000 | 27.0000 | 
|| 2012-03-24 19:57:00 | 345 | 40.0000 | 67.0000 | 
| 765432 | 2012-03-27 13:28:00 | 345 | -14.0000 | 53.0000 | 
+--------+---------------------+--------+-----------+----------+ 

起初我有兩個任務

1.計算交易的數量每個用戶的 2012(包括那些從第一個表誰在 第二個表都沒有,像123 SomeName00月,和那些誰沒有在2012年3月任 交易,如789 SomeName02)。

2.要計數每個用戶的期末餘額爲2012年3月 (同樣,包括那些從第一個表誰在 第二個表不和那些誰沒有在2012年3月 任何交易)。


我已經處理的第一個是這樣的:

SELECT name, COUNT(transactions.subscID) AS num_of_trns 
FROM subscribers 
LEFT JOIN transactions 
ON subscribers.subscID = transactions.subscID 
    AND transactions.date LIKE "2012-03%" 
GROUP BY subscribers.subscID 

看來工作,給出以下結果:

+------------+------------+ 
| name |num_of_trns | 
+------------+------------+ 
| SomeName00 |  0  | 
| SomeName01 |  3  | 
| SomeName02 |  0  | 
| SomeName03 |  2  | 
| SomeName04 |  2  | 
+------------+------------+ 

然後我試圖重用代碼,以便通過將COUNT(transactions.subscID)更改爲transactions.balance並向LEFT JOIN添加一個條件(transactions.date = MAX(transactions.date))來解決第二個任務,如下所示:

SELECT name, transactions.balance AS trns_blnc 
FROM subscribers 
LEFT JOIN transactions 
ON subscribers.subscID = transactions.subscID 
    AND transactions.date LIKE "2012-03%" 
    AND transactions.date = MAX(transactions.date) --this is incorrect 
GROUP BY subscribers.subscID 

但是這種方法證明是絕對錯誤的(我想,MySQL只是不明白我試圖比較哪些值)。

然後我決定利用第一個任務結果,再次將另一個transactions實例加入到它(如果我使用錯誤的術語),並且條件是實例的日期=舊錶的日期:

SELECT march_trns.name, balance FROM (
    SELECT name, date 
    FROM subscribers 
    LEFT JOIN transactions 
    ON subscribers.subscID = transactions.subscID 
     AND transactions.date LIKE "2012-03%" 
     GROUP BY subscribers.subscID 
) AS march_trns 
LEFT JOIN transactions AS transactions2 
ON march_trns.date = transactions2.date 

但很快就發現,march_trns.date和,因此,balance隨機選擇(或者我只是沒能找出其選擇的任何模式)的值中,滿足條件LIKE "2012-03%"。此外,我的結果表中有NULL(我猜,這是因爲我不再使用COUNT來計算所有行,包括。空值):

  Have:       Want: 
+------------+----------+  +------------+----------+ 
| name  | balance |  | name  | balance | 
+------------+----------+  +------------+----------+ 
| SomeName00 |  NULL |  | SomeName00 | 0.0000 | 
| SomeName01 | 90.0000 |  | SomeName01 | 60.0000 | 
| SomeName02 |  NULL |  | SomeName02 | 0.0000 | 
| SomeName03 | 2.0000 |  | SomeName03 | 2.0000 | 
| SomeName04 | 67.0000 |  | SomeName04 | 53.0000 | 
+------------+----------+  +------------+----------+ 

所以,我有兩個問題:

  • 我需要檢索月末餘額值
  • ,並打印出NULL值0秒。

如果你告訴我正確的方向,我會非常感激你。

+0

這不是您的查詢似乎返回隨機結果的一大驚喜。你寫的不是有效的標準SQL,而是一個MySQL特定的擴展。你可能會在文檔中找到這個頁面:[MySQL擴展到GROUP BY](http://dev.mysql.com/doc/refman/5.6/en/group-by-extensions.html)。 –

+0

'+ 1'提出非常明確的問題,提供具有期望結果':D'的樣本記錄。 –

+0

@Mark Byers謝謝,我會閱讀參考資料。 – Anton

回答

1
SELECT name, 
     COALESCE(COUNT(transactions.subscID), 0) AS num_of_trns, 
     COALESCE(d.balance,0) 
FROM subscribers 
     LEFT JOIN transactions 
      ON subscribers.subscID = transactions.subscID 
       AND transactions.date LIKE "2012-03%" 
     LEFT JOIN 
     (
      SELECT a.subscID, a.balance 
      FROM transactions a 
        INNER JOIN 
        (
         SELECT subscID, MAX(date) maxDate 
         FROM transactions 
         WHERE transactions.date LIKE "2012-03%" 
         GROUP BY subscID 
        ) b ON a.subscID = b.subscID AND 
          a.date = b.maxDate 

     ) d ON subscribers.subscID = d.subscID 
GROUP BY subscribers.subscID 
ORDER BY Name 

或通過使用YEARMONTH

SELECT name, 
     COALESCE(COUNT(transactions.subscID), 0) AS num_of_trns, 
     COALESCE(d.balance,0) 
FROM subscribers 
     LEFT JOIN transactions 
      ON subscribers.subscID = transactions.subscID 
       AND YEAR(transactions.date) = 2012 AND 
        MONTH(transactions.date) = 3 
     LEFT JOIN 
     (
      SELECT a.subscID, a.balance 
      FROM transactions a 
        INNER JOIN 
        (
         SELECT subscID, MAX(date) maxDate 
         FROM transactions 
         WHERE YEAR(transactions.date) = 2012 AND 
           MONTH(transactions.date) = 3 
         GROUP BY subscID 
        ) b ON a.subscID = b.subscID AND 
          a.date = b.maxDate 

     ) d ON subscribers.subscID = d.subscID 
GROUP BY subscribers.subscID 
ORDER BY Name 

SOURCE

+1

謝謝,約翰,我剛剛嘗試了第一個版本。它會爲三月交易返回正確的值,但其餘部分仍然爲NULL :-( – Anton

+0

可以添加記錄嗎? –

+1

我可以,但是......這種情況下的「記錄」是什麼?:-)無論如何,你的第二個查詢完美工作。非常感謝! – Anton

相關問題