Mysql 获取给定期间内分组项的最新值,包括零和空值

Mysql 获取给定期间内分组项的最新值,包括零和空值,mysql,sql,left-join,Mysql,Sql,Left Join,你能帮我看看我走的路是否对吗?我是SQL新手,所以有很多事情对我来说并不明显 假设我有两张桌子。 第一个是订户列表: subscribers +--------+------------+ |subscID | name | +--------+------------+ | 123 | SomeName00 | | 456 | SomeName01 | | 789 | SomeName02 | | 012 | SomeName03 | | 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).


我以这种方式处理了第一个问题:

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只是不知道我要比较哪些值)

然后,我决定利用第一个任务结果,在实例的日期=旧表的日期的条件下,再次将
事务的另一个实例
连接到它(如果我使用了错误的术语,很抱歉):

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\u trns.date
,结果,
balance
是在值中随机选择的(或者我只是没有找到任何选择模式),符合
如“2012-03%”
条件。此外,我的结果表中存在空值(我想,这是因为我不再使用
COUNT
来计算所有行,包括空值):

因此,我有两个问题:

  • 我需要检索月末余额值
  • 并将空值打印为
    0
    s
如果你给我指明正确的方向,我将不胜感激

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
或者使用

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
来源


您的查询似乎会返回随机结果,这并不奇怪。您编写的不是有效的标准SQL,而是特定于MySQL的扩展。您可能会发现文档中的这一页很有启发性:.
+1
提出了非常明确的问题,提供了具有预期结果的样本记录
:D
@Mark Byers谢谢,我会阅读参考资料。谢谢您,John,我刚刚尝试了第一个版本。它为3月份的事务返回正确的值,但其余事务仍有空值:-(我可以,但是……在本例中的“记录”是什么?:-)无论如何,您的第二个查询工作得很好。谢谢!回到我之前的投诉,要么我错误地删除了一些字符,要么在您的版本之前复制了代码,但第三行上只有“d.balance”,而不是“COALESCE(d.balance,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 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