MySQL中老年试算平衡报告的SQL查询

时间:2014-07-07 23:49:34

标签: mysql sql

到目前为止,我的查询产生了客户帐户的当前余额以及在生成报告后的以下几天内开具发票的总金额:0-30,30-60,60-90,90 +。

我坚持如何应用客户已经付款以准确反映每个发票期间的欠款。因此,如果某个帐户具有以下余额和上述期间开具发票的金额:

 Balance: $200     (current balance left owing on someones account)
    0-30: $20      ($20 invoice during a period of 0-30 days prior to generation of report)
   30-60: $100     
   60-90: $100     ($100 invoiced during 60-90 days prior)
     90+: $2500

我正在寻找的结果是:

 Balance: $200
    0-30: $20
   30-60: $100
   60-90: $80
     90+: $0

这是在应用了对此帐户进行的所有付款之后。如果他们已开票的总金额从0-3030-6060-9090+字段增加到2720美元,但他们只需支付200美元,我通过从发票总金额中减去当前余额,可以获得客户已支付的金额:$ 2720 - $ 200 = $ 2520

我想要做的是先将这些付款应用于最早的发票。如果他们已经支付了2720美元并且仅在90天以前开具了2500美元的发票,那么他们基本上不再欠这段时间的任何东西了。这留给我剩下的20美元用于下一个最早的发票期,将60-90天字段从100美元减少到80美元。

我不确定我是否采取了正确的方法开始。目前,我正在生成第一个示例(余额和给定期间开票的总金额),没有问题,作为下一个查询的子查询,我试图将付款应用于发票期间。

我已经提出了一个CASE表达式,用于将付款应用到90+字段,但我不确定如何“遍历”其他字段 - 跟踪我剩余的付款金额申请。

select account_number,

    Balance,
    case
        when Balance = 0
            or (total_invoices - Balance - `90+`) >= 0
            then 0
        else (total_invoices - Balance - `90+`)*-1
    end as `90+`,

    case
        when Balance = 0 then 0 else `60-90` end as `60-90`,

    case when Balance = 0 then 0 else `30-60` end as `30-60`,

    case
        when Balance = 0 then 0 else `0-30`
    end as `0-30`

from (
select account_number,

    round(sum(if(charge_type = 0, total*-1, total)),2) as "Balance",

    round(sum(
        if(charge_type != 0 
            and DATEDIFF(curdate(),trans_date) < 30, total, 0)
    ),2) as "0-30",

    round(sum(
        if(charge_type != 0 
            and DATEDIFF(curdate(),trans_date) between 30 and 60, total, 0)
    ),2) as "30-60",

    round(sum(
        if(charge_type != 0 
            and DATEDIFF(curdate(),trans_date) between 60 and 90, total, 0)
    ),2) as "60-90",

    round(sum(
        if(charge_type != 0 
            and DATEDIFF(curdate(),trans_date) >= 90, total, 0)
    ),2) as "90+",

    round(sum(
        if(charge_type != 0, total, 0)
    ),2) as "total_invoices"

from
    (select  #UNION current & archive
        account_number,
        trans_date,
        charge_type,
        total
    from
        invoices_and_transactions_archive
    UNION ALL
    select
        account_number,
        trans_date,
        charge_type,
        total
    from
        invoices_and_transactions
    where
        is_carry_forward = 0

    ) q1
group by account_number
) x

在这种情况下,似乎CASE表达式和IF函数可能会受到限制。另外,即使我确定了一些公式来获得正确的余额,理想情况下列不符合我想要的顺序,我将不得不做另一个子查询来反转它们。

编辑:这种方法有效。

select account_number,

    Balance,
    case
        when Balance = 0 then 0
        when (total_invoices - Balance - `30-60` - `60-90` - `90+`) > 0
            # leave negative result since their balance should be in credit.
            # The same situation for older invoices would require setting balance
            # to these invoices to zero, since it means there's still payments leftover
            # to apply to new invoices
            then `0-30` - (total_invoices - Balance - `30-60` - `60-90` - `90+`)
        else `0-30`
    end as `0-30`,

    case
        when Balance = 0 then 0
        when (total_invoices - Balance - `60-90` - `90+`) > 0
            then
                if((`30-60` - (total_invoices - Balance - `60-90` - `90+`) >= 0),
                    `30-60` - (total_invoices - Balance - `60-90` - `90+`), 0
                )
        else `30-60`
    end as `30-60`,

    case
        when Balance = 0 then 0
        when (total_invoices - Balance - `90+`) > 0
            then
                if((`60-90` - (total_invoices - Balance - `90+`) >= 0),
                    `60-90` - (total_invoices - Balance - `90+`), 0
                )
        else `60-90`
    end as `60-90`,

    if(Balance != 0 and (`90+` - (total_invoices - Balance) >= 0),
        `90+` - (total_invoices - Balance), 0
    )as `90+`

from (...)

1 个答案:

答案 0 :(得分:1)

SELECT account_number,
       Balance,
       `0-30` - (total_invoices - Balance - LEAST(`90+` + `60-90` + `30-60`, total_invoices - Balance)) AS `0-30`,
       `30-60` - (total_invoices - Balance - LEAST(`90+` + `60-90`, total_invoices - Balance)) AS `30-60`,
       `60-90` - (total_invoices - Balance - LEAST(`90+`, total_invoices - Balance)) AS `60-90`,
       GREATEST(0, `90+` - (total_invoices - Balance)) AS `90+`
FROM (...)

DEMO