如题,在数据量比较大的表中,我们常常需要按时间(年、月或日)分表,加上一个日期的字符串后缀。而这种情形下,当用户给定了起始和结束的时间字符串时,我们就需要根据这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即可)。而这常常应用在跨同类型的、按时间划分(时间作为字符串)
的表查询中。时间字符串的格式依实际情况而定~