2016-09-25 48 views
0

我有三個表。我想用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

回答

1

從這組數據的開始:

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

1

它被稱爲 「轉」。

 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