让报表完蛋去,超简单的方法完成任务
代价总是会有的,不是开发快就是效率低。如果你在收到类似于这类任务
本页显示所有等级段内的人数 |
|||||||||||||
等级 |
h府 |
g房 |
f场 |
e场 |
d场 |
c营 |
b营 |
a营 |
i馆 |
j院 |
k仓 |
l仓 |
m集 |
1-10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
10-20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
20-30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
30-40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
… |
|
|
|
|
|
|
|
|
|
|
|
|
|
至100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
表结构:
{
id
level
buildid (建筑类型)
uid
}
在我想到这个点子的时候不是为了解决上面这个查询,而是为了解决一堆这样的查询。
本来是以为用一些表达式来做,但是实际上我发现按照如下的方法更直观,没有任何学习成本。
如果你发现结果和你预想的不同。那么久断点下,看看生成的sql是否是正确的。这里有一个拼接sql字符串的东西。
当你还在想破脑筋为了这些无聊的东西发愁的时候,有这么一小段代码帮你偷工减料。
1、构造一个Result对象
public class Result { public List<String[]> select = new ArrayList<String[]>(); public List<String> where = new ArrayList<String>(); public List<String[]> group = new ArrayList<String[]>(); public List<String> order = new ArrayList<String>(); }
2、Result result = new Result();
result.select.add(new String[] { "府", "select count(*) from Building where buildid = 4 and ?" }); result.select.add(new String[] { "房", "select count(*) from Building where buildid = 10 and ?" }); result.select.add(new String[] { "场", "select count(*) from Building where buildid = 1 and ?" }); result.select.add(new String[] { "场", "select count(*) from Building where buildid = 2 and ?" }); result.select.add(new String[] { "场", "select count(*) from Building where buildid = 3 and ?" }); result.select.add(new String[] { " 兵", "select count(*) from Building where buildid = 5 and ?" }); result.select.add(new String[] { "兵", "select count(*) from Building where buildid = 6 and ?" }); result.select.add(new String[] { "兵", "select count(*) from Building where buildid = 7 and ?" }); result.select.add(new String[] { "馆", "select count(*) from Building where buildid = 12 and ?" }); result.select.add(new String[] { "院", "select count(*) from Building where buildid = 11 and ?" }); result.select.add(new String[] { "仓", "select count(*) from Building where buildid = 8 and ?" }); result.select.add(new String[] { "仓", "select count(*) from Building where buildid = 9 and ?" }); result.select.add(new String[] { "集", "select count(*) from Building where buildid = 13 and ?" }); result.group.add(new String[] { "1", "level >=1 and level < 10" }); result.group.add(new String[] { "2", "level >=10 and level < 20" }); result.group.add(new String[] { "3", "level >=20 and level < 30" }); result.group.add(new String[] { "4", "level >=30 and level < 40" }); result.group.add(new String[] { "5", "level >=40 and level < 50" }); result.group.add(new String[] { "6", "level >=50 and level < 60" }); result.group.add(new String[] { "7", "level >=60 and level < 70" }); result.group.add(new String[] { "8", "level >=70 and level < 80" }); result.group.add(new String[] { "9", "level >=80 and level < 90" }); result.group.add(new String[] { "10", "level >=90 and level < 100" }); List<User> users = playerMng.findByHql("from User where name = '" + userName + "'"); if (users.size() != 0) { result.where.add("userId = " + users.get(0).getUid()); }
3、select!
public List parserHQL(Result result) { List list = new ArrayList(); for (String[] garr : result.group) { // Map map = new HashMap(); Object[] arr = new Object[result.select.size() + 1]; int i = 1; arr[0] = garr[0]; for (String[] sarr : result.select) { Object obj = null; String sql = sarr[1].replace("?", garr[1]); String groupSql = ""; if (sql.indexOf("#") != -1) { groupSql = sql.split("#")[1]; sql = sql.split("#")[0]; } for (String where : result.where) { sql += " and " + where; } sql += groupSql; List l = dao.findByHql(sql); if (l != null && l.size() > 0) { obj = l.get(0); } // map.put(sarr[0], obj); arr[i] = obj; i++; } list.add(arr); } return list; }
构造Result 对象的时候别看字多,逻辑非常简单。不用去想什么sql怎么写。
groop list保存的是Y轴条件,
where list 保存的是总条件。如查询uid为xxx的 这个报表
select list 保存的是显示内容和查询sql(主)
数组第0个元素为显示内容,第一个元素为sql的条件。 这个条件会替换掉X轴sql里面的 ?
如果X轴是带GROUP的sql 并且还有总条件那么需要用#代替。
如果想order一下,这个功能还没加。不过也就是根据最终的list 排序而已。
如果想分页?我觉得这类查询不需要分页。
如果想优化性能?当然可以,毫无疑问虽然写了那么多。实际上一个结果集中大概80%的查询内容是可以从同一个sql结果集中取出结果。每合并一个查询结果会减少Y轴数量 个查询 ~
------------
这里只是抛砖引玉,只适合存在Y轴条件的查询。如果你优化的足够好,就像上面说的那样合并查询内容。实际上和你去捣鼓sql的效果一样。一般是不需要分页的,排序更不是问题。
原理就是 Y轴条件+X轴条件 一定是单一值,然后写个程序循环下 再把结果拼起来。
---再贴几个实现。
本页显示对应等级的数量,以及拥有对应等级的人数 |
||
等级 |
数量 |
人数 |
一级 |
|
|
二级 |
|
|
三级 |
|
|
四级 |
|
|
五级 |
|
|
六级 |
|
|
七级 |
|
|
八级 |
|
|
九级 |
|
|
Result result = new Result(); result.select.add(new String[] { "数量", "select count(*) from t_treasure where ?" }); result.select.add(new String[] { "人数", "select count(*) from (select count(*) from t_treasure where ? # group by user_Id) a" }); result.group.add(new String[] { "一级", "strong_Level = 1" }); result.group.add(new String[] { "二级", "strong_Level = 2" }); result.group.add(new String[] { "三级", "strong_Level = 3" }); result.group.add(new String[] { "四级", "strong_Level = 4" }); result.group.add(new String[] { "五级", "strong_Level = 5" }); result.group.add(new String[] { "六级", "strong_Level = 6" }); result.group.add(new String[] { "七级", "strong_Level = 7" }); result.group.add(new String[] { "八级", "strong_Level = 8" }); result.group.add(new String[] { "九级", "strong_Level = 9" });
----------
再更新一个。。。这个本来不想用这种方法的。。但是突然开始头痛。。。分页方式示例。让分页、排序也成浮云。
Result result = new Result(); result.select .add(new String[] { "金额", "select sum(num)/10 from t_gold_record where type = '53' and ?" }); result.select .add(new String[] { "总数", "select sum(num)/10 from t_gold_record where type in('47','58','59') and ?" }); result.select .add(new String[] { "未消耗数", "select sum(num)/10 from t_gold_record where type not in('47','58','59','53') and ?" }); Pagination pagination2 = mallMng .findBySql( "select date_format(record_time, '%Y-%m') from t_gold_record group by date_format(record_time, '%Y-%m') desc", pageNo, getCookieCount()); for (Object obj : pagination2.getList()) { result.group.add(new String[] { obj.toString(), "date_format(record_time, '%Y-%m') = '" + obj + "'" }); } List list = mallMng.parserSQL(result);
vf
表结构
{
id
type
num
uid
record_time
}
这次呢,没有Y轴了,表面上看起来没有Y轴 实际上Y轴大家心里都知道了。就是record_time 的月份 Y轴由一段查询结果构成,因为这段结果是分页的,相当于整个报表也是分页的!同时Y轴排序=对整个报表排序。