maG*_*aGz 2 pivot group-by linq-to-sql
我有一个需要在gridview中显示的TimeTable的以下数据集.目前,数据集的片段如下所示:
SessionNum TimeStart TimeStop Details
---------- --------- -------- -------
1 08:00 09:00 Math101
1 09:00 10:00 Comp102
1 11:00 12:00 Engn101
2 08:00 09:00 Comp102
2 09:00 10:00 Math101
2 10:00 11:00 Acco103
Run Code Online (Sandbox Code Playgroud)
总共有5个会话,我希望数据集看起来像:
TimeStart TimeStop Session1 Session2 ...
--------- -------- -------- -------- ---
08:00 09:00 Math101 Comp102
09:00 10:00 Comp102 Math101
10:00 11:00 - Acco103
11:00 12:00 Engn101 -
Run Code Online (Sandbox Code Playgroud)
正如您将看到的,不需要聚合功能......只是分组,但对于我的生活,我似乎无法绕过这一个.我有以下LINQ查询生成第一个数据集:
List<TimeTable> list = db.TimeTables.OrderBy(o => o.TimeStart).OrderBy(o => o.SessionNum).ToList();
Run Code Online (Sandbox Code Playgroud)
这工作得很好,并产生排序的数据集SessionNum,然后TimeStart.我尝试解决这个问题会引发以下查询:
var result = list.GroupBy(t => t.TimeStart).Select(s => new {
TimeStart = s.Key,
Session1 = s.Where(x => x.SessionNum == 1),
Session2 = s.Where(x => x.SessionNum == 2)
});
Run Code Online (Sandbox Code Playgroud)
这跑了,但不幸的是没有用.我知道一个GroupBy(或几个)是必需的,但是从这一点开始我有点迷失了.我真的很感激任何帮助解决这个问题.先感谢您!
您无法在LINQ中直接执行数据透视查询.你可以做的是创建一个这样的结构:
var record = new
{
TimeStart = "10:00",
TimeStop = "11:00",
Sessions = new [] { "-", "Acco103", },
};
Run Code Online (Sandbox Code Playgroud)
如果有这些记录的列表,则必须确保该Sessions属性的数组长度与整个数据集中的不同会话数相同.然后,您可以通过索引到数组来访问会话信息.
在查看查询后,这应该更有意义.
首先,在数据库中查询所需的数据:
var query =
from s in db.TimeTables
orderby s.TimeStop
orderby s.TimeStart
group s by new { s.TimeStart, s.TimeStop } into gss
select new
{
gss.Key.TimeStart,
gss.Key.TimeStop,
Sessions = gss.ToArray(),
};
Run Code Online (Sandbox Code Playgroud)
现在确定不同的会话集:
var sessionNums =
db.TimeTables
.Select(s => s.SessionNum)
.Distinct()
.OrderBy(n => n)
.ToArray();
Run Code Online (Sandbox Code Playgroud)
现在在内存中处理这些数据(注意.ToArray()调用query):
var process =
from q in query.ToArray()
let lookup = q.Sessions
.ToLookup(s => s.SessionNum, s => s.Details)
select new
{
q.TimeStart,
q.TimeStop,
Sessions = sessionNums
.Select(n => String.Join(
", ",
lookup[n].DefaultIfEmpty("-")))
.ToArray(),
};
Run Code Online (Sandbox Code Playgroud)
这是艰苦的工作.将lookup创建一个简单的方法来获取会话细节进行任何SessionNum.调用lookup[n].DefaultIfEmpty("-")确保每个会话至少有一个值.在String.Join确保如果源数据有两会在我们结束了一个价值,同时在同一会话数.
无论有多少会话,这个结果都是安全的,因为它只会扩展数组.
process查询的输出如下所示:

然后你可以做这个查询:
var result =
from p in process
select new
{
p.TimeStart,
p.TimeStop,
Session1 = p.Sessions[0],
Session2 = p.Sessions[1],
};
Run Code Online (Sandbox Code Playgroud)
这将有效地"转动"您的结果,但您需要明确地放入每个"SessionX"属性.
result查询的输出如下所示:
