2016-09-25 18 views
0

私は3つのテーブルを持っています。私はC#linqを使用して1つのテーブルにしたいと思います。たとえば :SQL Serverからlinqの1つのテーブルへの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(); 

あなたが唯一のいくつかの日を選択したい場合は、返すことができます1日あたりのプロパティを持つオブジェクトではなく、辞書を含むオブジェクト。

辞書は日とタスクを表す値を表すキーで、キーと値のペアが含まれます。これは、あなたが質問をするべきか明確ではないが、読みやすい形式であなたの質問をフォーマットしてみてください

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

あなたのコメントに基づいて@ylanter私は私の答えを更新しました、見てください – 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

@ silanter、私が知る限り、列はハードコードされている必要があります。 – Jules

関連する問題