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 |
| 543210 | 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 |
| 432109 | 2012-02-23 14:01:00 |   345  |  -30.0000 |  27.0000 |
| 012345 | 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年3月每个订阅者的交易次数(包括第一个表中不在第二个表中的,如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它来计算所有行,包括 NULL):

          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 值打印为0s。

如果你告诉我正确的方向,我会非常感激你。

4

1 回答 1

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

来源

于 2012-11-26T15:14:49.303 回答