有这样一个需求:表t_fun_task为任务表,有字段(taskid,taskname),表t_fun_logbook为日志表,有字段(logid,taskid,logdate),一个任务可持续多天,每天会记录一条日志。在查询表t_fun_task时,需将任务表中的 logdate 查询出来作为一列 logdates显示。
t_fun_task
t_fun_logbook
查询结果
此结果查询方法可以用存储过程轻松实现,这里我要介绍的是sqlserver for xml path语句的应用,在sql server中利用 for xml path 语句能够把查询的数据生成xml数据
且合并为一条数据,看以下示例:
select logdate from t_fun_logbook where taskid=231 for xml path
结果为:
2014-01-06t00:00:00
2014-01-07t00:00:00
首先,将日期格式转化为需要的格式:
select convert(varchar(100), logdate, 111) from t_fun_logbook where taskid=231 for xml path
结果变为:
2014/01/06
2014/01/07
select convert(varchar(100), logdate, 111) from t_fun_logbook where taskid=231 for xml path('')
现在两条结果之间很难区分,需要用下划线将其分隔开来,方法是在convert函数前面加上一个下划线:
select '_'+convert(varchar(100), logdate, 111) from t_fun_logbook where taskid=231 for xml path('')
结果:_2014/01/06_2014/01/07。
在分析了for xml path语句之后,就来将这个查询结果添加到对t_fun_task的查询结果中去。我的思路是先构建一个子查询,然后查询task表时left join这个子查询:
select t1.taskid,'taskname' as taskname,t2.logdates from t_fun_task t1left join (select taskid, logdates=(select '_'+convert(varchar(100), logdate, 111) from t_fun_logbook where taskid=t1.taskid for xml path('')) from t_fun_logbook t1 group by taskid) t2 on t2.taskid=t1.taskidorder by t1.taskid asc
运行以上sql后得到的结果为:
发现logdates值的第一个下划线应该去掉,于是修改sql,应用 stuff函数去掉第一个下划线:
select t1.taskid,'taskname' as taskname,t2.logdates from t_fun_task t1left join (select taskid, logdates=stuff((select '_'+convert(varchar(100), logdate, 111) from t_fun_logbook where taskid=t1.taskid for xml path('')),1,1,'') from t_fun_logbook t1 group by taskid) t2on t2.taskid=t1.taskidorder by t1.taskid asc
将结果转化为json 返回给前端之后,js按照下划线分隔这个字段的值,即可以得到一个任务下面日志的填写情况。
