On Sat, 2009-07-25 at 10:33 +1000, John Machin wrote:
> On 25/07/2009 6:17 AM, David Bicking wrote:
> > That works. Thanks!
> 
> It struck me that Pavel's revised query didn't mention the d2 column at 
> all, only d1:
> 

Thanks for the additional info. In real life, I added WHERE d1='X' OR
D2='X' to the inner subqeury. Yes, there are records where neither are
'X' and they are to be ignored.

> >> sum(case when d1='X' then 1 else -1 end) as act_sum,
> >> sum(case when d1='X' then amt else -amt end) as net
> 
> ... backtracking, it seems that you haven't stated anything about the 
> possibility of having 'X' in neither d1 nor d2. You may like to program 
> this along more defensive lines:
> 
> sqlite> create table source (id integer, d1 text, d2 text, amt int);
> sqlite> insert into source values(1, 'X', 'Y', 15);
> sqlite> insert into source values(2, 'X', 'Z',  6);
> sqlite> insert into source values(2, 'A', 'X',  7);
> sqlite> insert into source values(3, 'B', 'X', 12);
> sqlite> insert into source values(4, 'C', 'W', 99);
> sqlite> .headers on
> sqlite> select id,
>     ...>     case kind
>     ...>         when 1 then 'NEW'
>     ...>         when 2 then 'DROP'
>     ...>         when 3 then 'CHANGE'
>     ...>         else        'WHOOPS'
>     ...>     end as Action,
>     ...>     net
>     ...> from (
>     ...>     select id,
>     ...>         sum((d1='X') + (d2='X') * 2) as kind,
>     ...>         sum(((d1 = 'X') - (d2 = 'X')) * amt) as net
>     ...>     from source
>     ...>     group by id
>     ...>     )
>     ...> order by 2 desc
>     ...> ;
> id|Action|net
> 4|WHOOPS|0
> 1|NEW|15
> 3|DROP|-12
> 2|CHANGE|-1
> sqlite> select id,
>     ...> case when act_sum = 1 then 'NEW'
>     ...> when act_sum = 0 then 'CHANGE'
>     ...> else 'DROP'
>     ...> end as Action,
>     ...> net
>     ...> from
>     ...> (
>     ...> select id,
>     ...> sum(case when d1='X' then 1 else -1 end) as act_sum,
>     ...> sum(case when d1='X' then amt else -amt end) as net
>     ...> from Source
>     ...> group by id
>     ...> )
>     ...> order by 2 desc;
> id|Action|net
> 1|NEW|15
> 3|DROP|-12
> 4|DROP|-99
> 2|CHANGE|-1
> sqlite>
> 
> An accounting system where the sign of the amount is detached and has to 
> be obtained from another column is tedious and error-prone; obtaining it 
> from TWO columns is "interesting"; 

You must have never dealt with SAP. The values are all positive, and in
another column they have H or S to say if it is positive or negative. (H
and S being the initials of Credit and Debit in German. Or maybe those
initials are used because I work for the US division of a German
company. Not entirely sure.)

> a system where the nature of the 
> transaction or event is not recorded and has to be reverse-engineered 
> from circumstantial evidence is also "interesting" (especially where the 
> evidence spans more than one row) -- is this an existing system, or is 
> it a prototype that you could reconsider?
> 

The values are always what they are in the amt column, but this report
is tracking changes for a given date.

d1 and d2 are starting and ending dates. If you have an id that starts
on a given date, but has no prior record ending on that date, then it is
brand new. If one ends on a given date but there is no newer record
starting, then the item was dropped, and represents a decrease in the
total. If an item end son one date, and picks up with a new value, then
it changed. 

The format seems nice and compact. You can get the detail for any given
date by selecting WHERE target>=d1 and target<d2. And since items tend
to stay the same value over a long period of time, there is only one
record in the table to cover it. 

I was extracting the values for the target day and the day before into a
second table, and comparing the values, but I realized that I could grab
both values in one go by looking for the common dates in d1 and d2. I
just couldn't figure how to get the descriptive Action of New, Drop or
Change since multiple rows are involved. Given that I have used a
similar trick in calculating the "kind" value many times, I have been
kicking myself that I didn't see using it here.

I'm open to suggestions for other ways to implement this.

David


_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to