Subject | Re: [firebird-support] Re: Best table structure for Debit/Credit |
---|---|
Author | Svein Erling Tysvaer |
Post date | 2006-06-26T08:27:27Z |
Matthias Hanft wrote:
cases, is to use the IN construct (it may not work with character
columns, I don't quite remember). Add that the case statement doesn't
have to be limited to one column, and you get something like:
select sum (
case
when transtype IN ('C','X','F','L') and currency = 0 then...
or, to get your positive/negative bit, I would guess you could do (not
tested)
select
sum (
case when transtype IN ('C','X','F','L') then 1 else - 1 end
*
case currency
when 0 then amount/1.95583
when 1 then amount
else 0.00 /* never happens: don't sum */
end
requires all rows for the customer to have the cleared flag 0. If the
cleared flag is not 0, then you use NULL (not 0), and summing anything
containing NULL has to yield NULL (if there is one unknown, you can't
know the sum).
The HAVING clause can be useful, but only when you want something
working on your result set. From what you write, I'd rather use an
EXISTS(subselect) in the WHERE clause, if you intend it to be like you
wrote above:
EXISTS(select * from billing b2
where b2.custno = b.custno
and b2.cleared = 0)
more subselects. The one you probably want is this:
SUM(
case
when transtype = 'R'
and NOT EXISTS(select * from billing b2
where b2.custno = b.custno
and b2.transtype = 'P'
and b2.transdate >= b.transdate)
then 1 else 0 end)
HTH,
Set
>> Nested case statements are allowed:OK, you caught me - I copy-pasted your SQL. What you may do in some
>>
>> select
>> sum (
>> case transtype
>> when 'C','X','F','L':
>> case currency
>> when 0 then amount/1.95583
>> when 1 then amount
>> else 0.00 /* never happens: don't sum */
>> end
>> when 'D','A','M','Z':
>> case currency
>> when 0 then -amount/1.95583
>> when 1 then -amount
>> else 0.00 /* never happens: don't sum */
>> end
>> else 0.00 /* don't sum at all */
>> end
>> ) as customersum
>> from transactiontable
>> where custno=?
>
> OK, but putting it this way you have to specify the 1.95583
> division twice. Admittedly, the sign flag is already included
> in the division.
>
> Does a WHEN comma-seperated list really work? I just put it
> down that way for clarity, but I'm afraid in real life, it
> should read when transtype='C' or transtype='X' or...?!
cases, is to use the IN construct (it may not work with character
columns, I don't quite remember). Add that the case statement doesn't
have to be limited to one column, and you get something like:
select sum (
case
when transtype IN ('C','X','F','L') and currency = 0 then...
or, to get your positive/negative bit, I would guess you could do (not
tested)
select
sum (
case when transtype IN ('C','X','F','L') then 1 else - 1 end
*
case currency
when 0 then amount/1.95583
when 1 then amount
else 0.00 /* never happens: don't sum */
end
> Meanwhile, I have created 3 additional columns (number ofAre you sure this is what your code is doing? I'd say that your code
> reminders, date of last invoice, date of last payment) and
> extended the query from one customer to all customers of
> a company, showing only the customers with a non-zero
> balance (this means: who have at least one row where the
> "cleared" flag is still zero). Now it looks like this:
requires all rows for the customer to have the cleared flag 0. If the
cleared flag is not 0, then you use NULL (not 0), and summing anything
containing NULL has to yield NULL (if there is one unknown, you can't
know the sum).
The HAVING clause can be useful, but only when you want something
working on your result set. From what you write, I'd rather use an
EXISTS(subselect) in the WHERE clause, if you intend it to be like you
wrote above:
EXISTS(select * from billing b2
where b2.custno = b.custno
and b2.cleared = 0)
> selectWell, I guess you could do this two ways, both of them requiring one or
> b.custno,
> sum(
> case b.cleared
> when 0 then
> case b.currency
> when 0 then cast(b.amount/1.95583 as numeric(9,2))
> when 1 then b.amount
> else NULL
> end
> * t.factor
> else NULL
> end
> ) as balance,
> sum(
> case
> when b.transtype='R' and b.cleared=0 then 1 /* reminder */
> else NULL
> end
> ) as reminders,
> max(
> case t.invpaynone /* invoice or payment or none */
> when 'I' then b.transdate /* invoice */
> else NULL
> end
> ) as last_invoice,
> max(
> case t.invpaynone
> when 'P' then b.transdate /* payment */
> else NULL
> end
> ) as last_payment
> from billing b join transtypes t on b.transtype=t.transtype
> where company=?
> group by b.custno
> having
> sum(
> case b.cleared
> when 0 then 1
> else NULL
> end
> ) is not null
> order by b.custno;
>
> This works great - and now, my last wish is a column "number of
> reminders since last payment". So, the SUM of transtype='R' had
> to be "resetted" when a transtype='P' is encountered. Is this
> possible within an SQL statement at all?
more subselects. The one you probably want is this:
SUM(
case
when transtype = 'R'
and NOT EXISTS(select * from billing b2
where b2.custno = b.custno
and b2.transtype = 'P'
and b2.transdate >= b.transdate)
then 1 else 0 end)
HTH,
Set