So, I have a database with a particularly nasty design decision. We have people who belong to cost centres, usually only one, but sometimes with a prorata on two cost centres. The programmer responsable for creating the table denormalised things, so rather than having
EMP1 UNIT1 50% EMP1 UNIT2 50% EMP2 UNIT3 100% EMP3 UNIT1 100%
we have something that looks like
EMP1 UNIT1 UNIT2 50 50 EMP2 UNIT3 null 100 0 EMP3 UNIT1 null 100 0
That is, both cost centre ids in the same table, the second one usually null. It is a given that there will never be more than two. This table is of course an utter bitch to work with. Turns out we can cheat a bit, by only keeping track of the rate of the first centre, the second is just 100-first (which also helps cut down round-offs). Let us create a table to play with:
create table t1 ( id_person varchar(10), rate number(5,2), unit1 varchar(3), unit2 varchar(3), val1 number(10), val2 number(10) ); insert into t1 values ('alice', 1, 'U1', null, 10, 20); insert into t1 values ('bob', 1, 'U2', null, 4, 8); insert into t1 values ('carol', 0.5, 'U1', 'U2', 300, 600); insert into t1 values ('david', 0.2, 'U1', 'U3', 6000, 8000);
Now I want the sum the values val1 and val2 by unit, keeping in mind that for 'david', VAL1 6000 * 0.2 = 1200 is summed to U1, and the difference, 4800, to U3. Similarly, for VAL2, 1600 to U1 and 6400 to U3. In other words, I want the following result set:
U1 1360 1920 U2 154 308 U3 4800 6400
Now the only way that I can see is to:
This gives the following:
select S.UNIT UNIT ,sum(V1) V1_TOT ,sum(V2) V2_TOT from ( select unit1 UNIT ,sum(val1 * rate) V1 ,sum(val2 * rate) V2 from t1 group by unit1 union select unit2 UNIT ,sum(val1 - val1 * rate) V1 ,sum(val2 - val2 * rate) V2 from t1 where unit2 is not null group by unit2 ) S group by S.UNIT order by S.UNIT
That's pretty ugly. Is there a better way?