在项目的种种需求中,我们偶尔会遇到以下场景:

有如下一张表,记录了起点站、终点站、发车时间:

QQ截图20151217093746.png


现需要将此表格中的数据查询出来,以如下形式在页面中展现,以起点站和终点站分组,显示当天发车的时间表:

QQ截图20151217095924.png


按傻瓜式的做法,我们通常会将表中的数据原样查询出来,然后在.net代码中遍历查询结果,另外构建一个DataTable或者集合进行数据变形。这种做法在编码时的确省心省力,但若查询数据量较大,代码的执行效率就不高了。


这里推荐使用FOR XML PATH的语句进行查询,贴上代码

SELECT 
    StartStation, 
    TerminalStation, 
    StartTimeList= STUFF((
        SELECT '、'+DATENAME(HOUR, tblJoin.StartTime) + ':' + DATENAME(MINUTE, tblJoin.StartTime) 
        FROM tblTest tblJoin 
        WHERE 
            tblJoin.StartStation=tblMain.StartStation 
            AND tblJoin.TerminalStation=tblMain.TerminalStation 
            FOR XML PATH('')
        ),1,1,'')
FROM tblTest tblMain
WHERE tblMain.StartTime>='2015-12-17 00:00:00' AND tblMain.StartTime<'2015-12-18 00:00:00'
GROUP BY StartStation, TerminalStation

用FOR XML PATH拼接时间字段,并用STUFF截取拼接的第一个顿号(、),运行后成功获取到想要的数据形式。



当然,对于不了解SQL,又不想在.net中使用那么冗长的数据变形代码的同学们来说,LINQ就是你的福音了,以下贴上LINQ代码截图,也可以达到相同的页面展示效果,只是代码执行效率没有直接用SQL的效率高,代码还是相当简洁的:

var busSchedules = GetBusScheduleList();
var data = from s in busSchedules
            group s by new
            {
                s.StartStation,
                s.TerminalStation
            }
            into g
            let startTimeList = g.Select(p => p.StartTime.ToString("mm:ss")).ToArray()
            select new
            {
                StartStation = g.Key.StartStation,
                TerminalStation = g.Key.TerminalStation,
                StartTimeList = string.Join("、", startTimeList)
            };


需要查看SQL和LINQ代码的同学请下载附件:

Demo.zip