从sql服务器到一个表的C#linq查询

问题描述:

我有三个表。我想用C#linq变成一个表。 例如:从sql服务器到一个表的C#linq查询

Schedule: 
+------+--------+--------+ 
| Name | DateId | TaskId | 
+------+--------+--------+ 
| John |  2 |  32 | 
| John |  3 |  31 | 
| Mary |  1 |  33 | 
| Mary |  2 |  31 | 
| Tom |  1 |  34 | 
| Tom |  2 |  31 | 
| Tom |  3 |  33 | 
+------+--------+--------+ 

日期:

+----+------------+ 
| Id | Date | 
+----+------------+ 
| 1 | Monday  | 
| 2 | Tuesday | 
| 3 | Wednesday | 
| 4 | Thursday | 
| 5 | Friday  | 
+----+------------+ 

任务:

+----+----------+ 
| Id | Task | 
+----+----------+ 
| 31 | School | 
| 32 | Homework | 
| 33 | Break | 
| 34 | Teaching | 
+----+----------+ 

我想有这样一个表:

+--------+----------+----------+-----------+----------+ 
| Person | Monday | Tuesday | Wednesday | Thursday | 
+--------+----------+----------+-----------+----------+ 
| John |   | Homework | School |   | 
| Mary | Break | School |   |   | 
| Tom | Teaching | School | Break  |   | 
+--------+----------+----------+-----------+----------+ 

我想不出任何好的方式doin g这个。

任何建议将是有益的

感谢

+2

请尝试以可读格式来格式化你的问题,这显然不是你应该如何问一个问题。 –

+0

[this]的可能重复(http://stackoverflow.com/questions/9720225/how-to-perform-join-between-multiple-tables-in-linq-lambda)。 – Han

+0

你需要**透视表**从这里,你可以参考这个[链接](http://stackoverflow.com/questions/167304/is-it-possible-to-pivot-data-using-linq) – Keppy

从这组数据的开始:

var schedules = new[] { new { Name = "John", DateId = 2, TaskId = 32}, 
          new { Name = "John", DateId = 3, TaskId = 31}, 
          new { Name = "Mary", DateId = 1, TaskId = 33}, 
          new { Name = "Mary", DateId = 2, TaskId = 31}, 
          new { Name = "Tom", DateId = 1, TaskId = 34}, 
          new { Name = "Tom", DateId = 2, TaskId = 31}, 
          new { Name = "Tom", DateId = 3, TaskId = 33} 
         }; 

    var dates = new[] { new { DateId = 1, Desc = "Monday"}, 
         new { DateId = 2, Desc = "Tuesday"}, 
         new { DateId = 3, Desc = "Wednesday"}, 
         new { DateId = 4, Desc = "Thursday"}, 
         new { DateId = 5, Desc = "Friday"} 
         }; 

    var tasks = new[] { new { TaskId = 31, Desc = "School"}, 
         new { TaskId = 32, Desc = "Homework"}, 
         new { TaskId = 33, Desc = "Break"}, 
         new { TaskId = 34, Desc = "Teaching"} 
         }; 

你可以做如下:

var result = schedules 
    // First you join the three tables 
    .Join(dates, s => s.DateId, d => d.DateId, (s, d) => new {s, d}) 
    .Join(tasks, s => s.s.TaskId, t => t.TaskId, (sd, t) => new { Person = sd.s, Date = sd.d, Task = t }) 
    // Then you Group by the person name 
    .GroupBy(j => j.Person.Name) 
    // Finally you compose the final object extracting from the list of task the correct task for the current day 
    .Select(group => new 
    { 
     Person = group.Key, 
     Monday = group.Where(g => g.Date.DateId == 1).Select(g => g.Task.Desc).FirstOrDefault(), 
     Tuesday = group.Where(g => g.Date.DateId == 2).Select(g => g.Task.Desc).FirstOrDefault(), 
     Wednesday = group.Where(g => g.Date.DateId == 3).Select(g => g.Task.Desc).FirstOrDefault(), 
     Thursday = group.Where(g => g.Date.DateId == 4).Select(g => g.Task.Desc).FirstOrDefault(), 
     Friday = group.Where(g => g.Date.DateId == 5).Select(g => g.Task.Desc).FirstOrDefault() 
    }) 
    .ToList(); 

如果你只需要选择一些日子,你可以返回包含字典的对象,而不是每天有属性的对象。

字典将包含键值对,其中代表日期的键和代表任务的值。

请看下面的代码:

var filter = new[] {2, 3}; 

    var filteredResult = schedules 
     .Join(dates, s => s.DateId, d => d.DateId, (s, d) => new{ s, d}) 
     .Join(tasks, s => s.s.TaskId, t => t.TaskId, (sd, t) => new { Person = sd.s, Date = sd.d, Task = t }) 
     .Where(x => filter.Contains(x.Date.DateId)) 
     .GroupBy(x => x.Person.Name) 
     .Select(group => new 
       { 
        Person = group.Key, 
        TasksByDay = group.ToDictionary(o => o.Date.Desc, o => o.Task.Desc) 
       }) 
     .ToList(); 


    foreach (var item in filteredResult) 
    { 
     System.Console.WriteLine(item.Person); 
     foreach (var keyvaluepair in item.TasksByDay) 
     { 
      System.Console.WriteLine(keyvaluepair.Key + " - " + keyvaluepair.Value); 
     } 
     System.Console.WriteLine("---"); 
    } 
+0

有没有办法动态选择列?例如,如果我现在只想要周一和周五,稍后我只想看周三。 我可以通过一个变量来过滤我想要的列。我想选择我想要的栏目。 – sylanter

+0

@sylanter根据你的评论我更新了我的答案,请看看 – user449689

它被称为 “转”。

 var persons = new[] { new { name="John", dateId=2,taskId=32}, 
           new { name="John", dateId=3,taskId=31}, 
           new { name="Mary", dateId=1,taskId=33}, 
           new { name="Mary", dateId=2,taskId=31}, 
           new { name="Tom", dateId=1,taskId=34}, 
           new { name="Tom", dateId=2,taskId=31}, 
           new { name="Tom", dateId=3,taskId=33} 
          }; 

     var dates = new[] { new { dateId=1, desc="Monday"}, 
          new { dateId=2, desc="Tuesday"}, 
          new { dateId=3, desc="Wednesday"}, 
          new { dateId=4, desc="Thursday"}, 
          new { dateId=5, desc="Friday"} 
          }; 

     var tasks = new[] { new { taskId=31, desc="School"}, 
          new { taskId=32, desc="Homework"}, 
          new { taskId=33, desc="Break"}, 
          new { taskId=34, desc="Teaching"} 
          }; 

     var qry = from p in (from p in persons 
          join d in dates on p.dateId equals d.dateId 
          join t in tasks on (int)p.taskId equals (int)t.taskId 
          select new { name = p.name, monday = d.dateId == 1 ? t.desc : "", tuesday = d.dateId == 2 ? t.desc : "", wednesday = d.dateId == 3 ? t.desc : "", thursday = d.dateId == 4 ? t.desc : "", friday = d.dateId == 5 ? t.desc : "" }) 
        group p by p.name into q 
        select new { q.Key, monday=q.Max(a => a.monday),tuesday=q.Max(a => a.tuesday), wednesday = q.Max(a=>a.wednesday), thursday = q.Max(a => a.thursday), friday=q.Max(a => a.friday)}; 

     foreach (var a in qry.ToList()) 
     { 
      Console.WriteLine(String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}",a.Key, a.monday, a.tuesday, a.wednesday, a.thursday, a.friday)); 
     } 
+0

是有动态选择列的方法吗?例如,如果我现在只想要周一和周五,稍后我只想看周三。 我可以通过一个变量来过滤我想要的列。我想选择我想要的栏目。 – sylanter

+0

@sylanter,据我所知,这个列必须是硬编码的。 – Jules