mysql - 获取给定时间段内分组项目的最新值,包括。零和空值

标签 mysql sql left-join

你能帮我看看我走的路是否正确吗?我是 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 月(包括第一张表中不在 第二张 table ,比如 123 SomeName00,还有那些没有任何 2012 年 3 月的交易,例如 789 SomeName02)。

2. 计算 2012 年 3 月每个订阅者的期末余额 (同样,包括第一张表中不在 二表和三月份没有任何交易的表 2012)。


我已经这样处理了第一个:

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

如果你能告诉我正确的方向,我将不胜感激。

最佳答案

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

来源

关于mysql - 获取给定时间段内分组项目的最新值,包括。零和空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13567474/

相关文章:

mysql - 从 bash 脚本运行 "mysql"命令

php - 如何将mysql表数据写入excel文件但不下载只存储文件

java - 获取使用 Hibernate 映射的属性的列名

sql - 根据条件从另一个表中选择插入一个表

MySQL - 连接2个表的多列

mysql - 在 mysql 中使用更新限制

MySQL 在一个表中查找在另一个表中没有列值的记录

php - 在php中计算从过去到现在的持续时间

java - Hibernate 使用注释将多表映射到一张表

涉及join的MySQL select语句