iReport variable incrementor usage with list component
I have a typical MySQL report listing one 'Item' per page. One of the fields is min_price. I would like to have my detail band list a fixed number (lets say 15) 'bid amounts' for each item, computed based on this starting price, plus a 'sliding scale' passed in as a report parameter as follows:
<parameter name="bidIncrementMap" class="java.util.TreeMap">
<defaultValueExpression><![CDATA[{10,1},{25,2},{50,5},{100,10},{250,20},{500,25},{9999,50}"]]></defaultValueExpression>
</parameter>
For a separate purpose, I already have a 开发者_高级运维table called alphabet with 26 rows id=1..26, letter=A..Z - this makes a convenient table to get a simple list of 15 integers.
So to get the bid increment value corresponding to a given number, I think it would be:
$P{bidIncrementMap}.floorEntry($F{each_bid}).getValue()
... but what I am trying to do is use the bid increment for each row to get the next row's value.
Also I should mention for packaging reasons, I need this to be a self-contained .jrxml that compiles to .jasper without any new custom classes on the classpath.
I feel like I'm real close.. can someone help me with the missing piece here? (FYI, I'm a Java and SQL expert but a Jasper newbie, liking what I see so far...) I think I need to somehow declare a variable and use this map to increment it each time, then somehow get the list component to show my sequence - I'd prefer to have it all one report since I can't see reusing such a subreport but an example of either way would be awesome.
I messed around a bit with a SQL expression using an @ variable and a complex if statement - This is NOT the focus of my question, but I include it to illustrate what I'm trying to achieve here:
mysql> select a.id, i.name, i.min_price, @b:=if(a.id=1,i.min_price,@b+if(@b<10,1,if(@b<25,2,if(@b<50,5,if(@b<100,10,if(@b<250,20,if
@b<500,25,50))))))) bid from items i, alphabet a where a.id<=15 and i.id=27 order by a.id;
+----+---------------+-----------+--------+
| id | name | min_price | bid |
+----+---------------+-----------+--------+
| 1 | My Item Name | 40.00 | 40.00 |
| 2 | My Item Name | 40.00 | 45.00 |
| 3 | My Item Name | 40.00 | 50.00 |
| 4 | My Item Name | 40.00 | 60.00 |
| 5 | My Item Name | 40.00 | 70.00 |
| 6 | My Item Name | 40.00 | 80.00 |
| 7 | My Item Name | 40.00 | 90.00 |
| 8 | My Item Name | 40.00 | 100.00 |
| 9 | My Item Name | 40.00 | 120.00 |
| 10 | My Item Name | 40.00 | 140.00 |
| 11 | My Item Name | 40.00 | 160.00 |
| 12 | My Item Name | 40.00 | 180.00 |
| 13 | My Item Name | 40.00 | 200.00 |
| 14 | My Item Name | 40.00 | 220.00 |
| 15 | My Item Name | 40.00 | 240.00 |
+----+---------------+-----------+--------+
15 rows in set (0.00 sec)
OK, I figured out a solution - might help someone else:
Rather than try initialize the default value for that bidIncrementMap (that was the part I was struggling with - I think it's not possible in Java without static block which isn't allowed here), I punted and decided to use SQL instead. I setup a table with the bid sequence as follows:
create table bid_sequence (id int not null auto_increment primary key, bid numeric(10,2) not null);
insert into bid_sequence (bid) (select @p:=if(items.id=1,1,@p+if(@p<10,1,if(@p<30,2,if(@p<80,5,if(@p<140,10,if(@p<300,20,if(@p<500,25,50))))))) bid from items order by items.id limit 1000);
In the insert statement, the items table could be any handy table with > (arbitrary upper limit) 1000 rows.
Then, for my subreport I have this much simpler query:
select if(bid=$P{min_price},@p:=1,@p:=@p+1) as seat, bid from (
select $P{min_price} as bid from dual
union select bid from bid_sequence where bid >= $P{min_price} limit 15) a
(The extra union is because the starting value might be between elements in the sequence, so rather than round up or down, I just prepend it and then the union prevents a duplicate.)
So the only downside is that I have a fixed upper limit on my sequence, so I can only handle price ranges up to $48K or so - for me, that's fine.
精彩评论