如题,在数据量比较大的表中,我们常常需要按时间(年、月或日)分表,加上一个日期的字符串后缀。而这种情形下,当用户给定了起始和结束的时间字符串时,我们就需要根据这2个字符串
判断中间到底跨越了几张同类型的按时间作为后缀的表。。
通常,用union all直接将多个表的查询语句拼接在一条sql里面,而非每张表都分别查询一次,再把结果集给addAll,这样造成跟db的多次交互,影响效率,不太建议……
跨表查询的sql拼接思想:
1)先判断起始和结束字符串代表的时间是不是在同一张表,若是,sql里面不用union all操作,一张表的时间between 起始时间and结束时间 即可;
2)若不是同一张表,判断起始和结束之间隔了几张按时间命名的同类型表,sql里循环拼接union all,并只需在起始表里的时间大于等于起始字符串;结束表的时间小于等于结束字符串;中间
拼接的几张表不需要时间过滤;但结束表的也需要union all;
3)每张表的select语句都需用()围起来,再union all成一条sql语句。
问题的关键在于,如何搞定如题所示的需求~~ 以下为关键的测试代码,特此记录下,以便以后用得着:
public static String DAY_DIMEN = "day"; public static String MONTH_DIMEN = "month"; public static String YEAR_DIMEN = "year"; public static List<String> getIntervalPeriods(String startDate, String endDate, String dimen) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(); int cVal = 0; if(StringUtils.equals(dimen, DAY_DIMEN)) { sdf = new SimpleDateFormat("yyyyMMdd"); cVal = Calendar.DATE; }else if(StringUtils.equals(dimen, MONTH_DIMEN)) { sdf = new SimpleDateFormat("yyyyMM"); cVal = Calendar.MONTH; }else if(StringUtils.equals(dimen, YEAR_DIMEN)) { sdf = new SimpleDateFormat("yyyy"); cVal = Calendar.YEAR; } Calendar c_begin = Calendar.getInstance(); Calendar c_end = Calendar.getInstance(); Date d_begin = sdf.parse(startDate); Date d_end = sdf.parse(endDate); c_begin.setTime(d_begin); c_end.setTime(d_end); List<String> dates = new ArrayList<String>(); dates.add(startDate); while(c_begin.before(c_end)) { c_begin.add(cVal, 1); String dateStr = sdf.format(c_begin.getTime()); dates.add(dateStr); } // dates.add(endDate); return dates; }
我们使用main方法测试一番:
1.测试"天"
List<String> strs = getIntervalPeriods("20151128","20151128",DAY_DIMEN);//测不跨天 System.out.println(strs); strs = getIntervalPeriods("20150908","20150910",DAY_DIMEN);//测不跨月的天 System.out.println(strs); strs = getIntervalPeriods("20151128","20151205",DAY_DIMEN);//测跨年跨月的天 System.out.println(strs);
运行结果:
[20151128]
[20150908, 20150909, 20150910]
[20151128, 20151129, 20151130, 20151201, 20151202, 20151203, 20151204, 20151205]
2.测试"月"
List<String> strs = getIntervalPeriods("201511","201603",MONTH_DIMEN);//测跨年的月 System.out.println(strs); strs = getIntervalPeriods("201509","201509",MONTH_DIMEN);//测不跨月 System.out.println(strs); strs = getIntervalPeriods("201509","201512",MONTH_DIMEN);//测不跨年的月 System.out.println(strs);
运行结果:
[201511, 201512, 201601, 201602, 201603]
[201509]
[201509, 201510, 201511, 201512]
3.测试"年"
List<String> strs = getIntervalPeriods("2015","2018",YEAR_DIMEN);//测跨年 System.out.println(strs); strs = getIntervalPeriods("2015","2015",YEAR_DIMEN);//测不跨年 System.out.println(strs);
运行结果:
[2015, 2016, 2017, 2018]
[2015]
测试成功,以上的工具代码是十分有用滴,可以准确求出给定起始和结束时间字符串中间的时间字符串(如不需要头尾,remove即可)。而这常常应用在跨同类型的、按时间划分(时间作为字符串)
的表查询中。时间字符串的格式依实际情况而定~