在where子句中使用IFNULL

时间:2018-01-29 07:52:30

标签: mysql sql

我的SQL语句没有返回特定结果的任何结果。

    SELECT statementbalance AS 'BringForwardFromPreviousDay', 
IFNULL((SELECT SUM(statementdebit) FROM statement WHERE merchantid = '4' AND statementdate = '2018-01-08'),0) AS 'TotalDebit',
IFNULL((SELECT SUM(statementcredit) FROM statement WHERE merchantid = '4' AND statementdate = '2018-01-08'),0) AS 'TotalCredit',
IFNULL((SELECT statementbalance FROM statement WHERE merchantid = '4' AND statementdate <= '2018-01-08' ORDER BY transactionid DESC LIMIT 1),0) AS 'TotalBalance'
FROM statement 
WHERE merchantid = '4' and statementdate <= '2018-01-07'
ORDER BY transactionid DESC LIMIT 1

SQL语句用于捕获今天'2018-01-08'和前几天'2018-01-07'的数据,并获取最后记录的数据,因此'<=' 由于merchantid = '4'是新添加的商家,因此无法从<= 2018-01-07抓取任何数据,因此我希望它返回0而不是null,并阻止其他数据返回null

我尝试在ifnull上添加statementnbalance,但它仍会返回null,我只能考虑将ifnull包含在where条款中,但我尝试过无济于事。

以下是使用merchantid '2'的方法工作正常。

http://sqlfiddle.com/#!9/7cae3e0/1

3 个答案:

答案 0 :(得分:3)

我认为这就是你想要的:

select
    x.merchantid                       as merchantid,
    ifnull(c.previous_days_balance, 0) as BringForwardFormPreviousDay,
    ifnull(a.latest_total_debit, 0)    as TotalDebit,
    ifnull(a.latest_total_credit, 0)   as TotalCredit,
    ifnull(b.latest_balance, 0)        as LatestBalance
from
    (
        select distinct merchantid from statement
    ) x
    left outer join
    (
        select
            merchantid, 
            sum(statementdebit) as latest_total_debit,
            sum(statementcredit) as latest_total_credit
        from
            statement
        where
            statementdate = '2018-01-08'
        group by
            merchantid
    ) a
    on x.merchantid = a.merchantid
    left outer join
    (
        select
            merchantid,
            statementbalance as latest_balance
        from
            statement
        where
            (merchantid, transactionid) in
            (
                select
                    merchantid,
                    max(transactionid)
                from
                    statement
                where
                    statementdate = '2018-01-08'
                group by
                    merchantid
            )
    ) b
    on x.merchantid = b.merchantid
    left outer join
    (
        select
            merchantid,
            statementbalance as previous_days_balance
        from
            statement
        where
            (merchantid, transactionid) in
            (
                select
                    merchantid,
                    max(transactionid)
                from
                    statement
                where
                    statementdate <= '2018-01-07'
                group by
                    merchantid
            )
    ) c
    on x.merchantid = c.merchantid;

我添加了另一行来说明额外的情况:

INSERT INTO statement VALUES ('99', '5', '131', 'Purchase: TopUp Cheezy', '2018-01-05', '23:35:31', '38.20', '0.00', '5000.00');

结果是:

+------------+-----------------------------+------------+-------------+----------------+
| merchantid | BringForwardFormPreviousDay | TotalDebit | TotalCredit | LatestBalance  |
+------------+-----------------------------+------------+-------------+----------------+
|          1 |                          35 |         15 |           0 |              5 |
|          2 |                      182.33 |        4.9 |           0 |         177.43 |
|          4 |                           0 |      95.48 |         200 |         104.52 |
|          5 |                        5000 |          0 |           0 |              0 |
+------------+-----------------------------+------------+-------------+----------------+
4 rows in set (0.00 sec)

这假设transactionId随时间不断增加。这不是一个完全安全的假设。最好使用时间戳而不是事务的日期,这样你就可以找到最新的(或者是今天之前的最新版本)。我看到你确实有声明时间但是有一个单独的列...

答案 1 :(得分:1)

查询没有返回任何内容,因为没有要返回的数据符合您的where子句。您可以做的是在整个选择语句中使用IFNULL

SELECT ifnull((SELECT statementbalance AS 'BringForwardFromPreviousDay'
               FROM statement 
               WHERE merchantid = '4'
                   AND statementdate <= '2018-01-07'
               ORDER BY transactionid DESC LIMIT 1), 0)

从那里开始工作。但是,您的语句只能包含一列,因此您必须将其用于存储过程,或者您必须在其他位置处理此问题(可能在您的代码中?)

答案 2 :(得分:0)

您需要使用LEFT JOIN来允许不存在的行。

SELECT IFNULL(t3.statementbalance, 0) AS BringForwardFromPreviousDay,
        t1.TotalDebit, t1.TotalCredit, t2.TotalBalance
FROM (SELECT SUM(statementdebit) AS TotalDebit,
             SUM(statementcredit) AS TotalCredit
      FROM statement
      WHERE merchantId = '4' AND statementdate = '2018-01-08') AS t1
CROSS JOIN (
      SELECT statementbalance AS TotalBalance
      FROM statement
      WHERE merchantId = '4' AND statementdate <= '2018-01-08'
      ORDER BY statementdate DESC
      LIMIT 1) AS t2
LEFT JOIN (
    SELECT statementbalance
    FROM statement 
    WHERE t3.merchantID = '4' AND t3.statementdate <= '2018-01-07'
    ORDER BY statementdate DESC
    LIMIT 1) ON 1=1