2015-07-02 2 views
6

У меня есть users стол:Объединить таблицы, используя значения строк в колонке LINQ C# SQL

Id | Name | Age 
-------------------- 
1 | Steve | 21 
2 | Jack | 17 
3 | Alice | 25 
4 | Harry | 14 

У меня также есть таблица, содержащая дополнительную информацию о пользователе:

UId | Key | Value 
---------------------- 
1 | Height | 70 
2 | Height | 65 
2 | Eyes | Blue 
4 | Height | 51 
3 | Hair | Brown 
1 | Eyes | Green 

The UId ссылки столбцов в Id столбец в таблице users. Как вы можете видеть, не все пользователи имеют такую ​​же дополнительную информацию. У Алисы нет значения высоты, только Джек имеет значение цвета глаза и т. Д.

Есть ли способ объединить эти данные в одну таблицу динамически с использованием C# и LINQ запросов, чтобы результат был примерно таким :

Id | Name | Age | Height | Eyes | Hair 
------------------------------------------ 
1 | Steve | 21 | 70 | Green |  
2 | Jack | 17 | 65 | Blue |  
3 | Alice | 25 |  |  | Brown 
4 | Harry | 14 | 51 | 

Если у пользователя нет значения для столбца, оно может оставаться пустым/null. Требует ли это какой-то поворот данных?

+1

проверка это поможет вам http://stackoverflow.com/questions/14066679/using-piv ot-table-in-linq –

+0

Является ли дополнительная информационная таблица пользователя постоянной или должны быть доступны новые ключи без изменения LINQ? – Matt

+0

Вы считаете, что скрываете свое «я» после того, как вы удалили свой нисходящий андер? Уже Stackoverflow уведомляется о вашей деятельности с любыми подробностями. Это не место для игры, это место, где вы можете узнать и поделиться своими знаниями. –

ответ

3

Для случая, Ваша информация пользовательские поля постоянны:

var result = users.GroupJoin(details, 
      user => user.Id, 
      detail => detail.Id, 
      (user, detail) => new 
      { 
       user.Id, 
       user.Name, 
       user.Age, 
       Height = detail.SingleOrDefault(x => x.Key == "Height").Value, 
       Eyes = detail.SingleOrDefault(x => x.Key == "Eyes").Value, 
       Hair = detail.SingleOrDefault(x => x.Key == "Hair").Value, 
      }); 
+0

Спасибо за ваш ответ! Хотя было несколько ответов, которые дали желаемые результаты, ваш был самым простым, на мой взгляд. –

+0

Но будьте осторожны, если возможны несколько значений UId/Key. Затем вы должны использовать FirstOrDefault или LastOrDefault. – Matt

+0

Да, это действительно точная ситуация. Возможны множественные UId, поэтому я использовал 'FirstOrDefault'. Еще раз спасибо! –

0

попробовать этот запрос,

var objlist=(form a in contex.user 
       join b in contex.UserDetails on a.id equals a.Uid into gj 
       from subpet in gj.DefaultIfEmpty() 
         select new { Id=a.id, Name=a.name, Age=a.age, Height =subpet.Height,Eyes=subpet.Eyes, Hair=subpet.Hair}).ToList(); 
+1

В строке 2 это должно быть 'from b in' вместо' from b in', потому что я получаю синтаксическую ошибку, используя 'in'. Я также получаю сообщение об ошибке в разделе 'join', в котором говорится' недопустимый термин выражения 'join''. Спасибо за ответ! –

+0

ОК Теперь проверьте. Не говорите спасибо, учитывая правильную отметку запроса и проголосовав –

+0

Где появились свойства subpet.Height, subpet.Eyes, subpet.Hair? Этот запрос не будет работать. –

2

Вы можете сделать это, используя GroupJoin, пример:

var users = new List<Tuple<int, string, int>> { 
    Tuple.Create(1, "Steve", 21), 
    Tuple.Create(2, "Jack", 17), 
    Tuple.Create(3, "Alice", 25), 
    Tuple.Create(4, "Harry", 14) 
}; 
var userInfos = new List<Tuple<int, string, string>> { 
    Tuple.Create(1, "Height", "70"), 
    Tuple.Create(2, "Height", "65"), 
    Tuple.Create(2, "Eyes", "Blue"), 
    Tuple.Create(4, "Height", "51"), 
    Tuple.Create(3, "Hair", "Brown"), 
    Tuple.Create(1, "Eyes", "Green"), 
}; 
var query = users.GroupJoin(userInfos, 
    u => u.Item1, 
    ui => ui.Item1, 
    (u, infos) => new { User = u, Infos = infos }); 
var result = query.Select(qi => new 
{ 
    Id = qi.User.Item1, 
    Name = qi.User.Item2, 
    Age = qi.User.Item3, 
    Height = qi.Infos.Where(i => i.Item2 == "Height").Select(i => i.Item3).SingleOrDefault(), 
    Eyes = qi.Infos.Where(i => i.Item2 == "Eyes").Select(i => i.Item3).SingleOrDefault(), 
    Hair = qi.Infos.Where(i => i.Item2 == "Hair").Select(i => i.Item3).SingleOrDefault() 
}); 
+0

Можете ли вы объяснить, что такое 'Item1',' Item2' и 'Item3'? Потому что я заметил, что они нигде не объявлены. Спасибо за ответ! –

+1

@ Reece Kenney Это свойства класса ['Tuple'] (https://msdn.microsoft.com/en-us/library/system.tuple (v = vs.110) .aspx), который используется для создайте элементы 'users' и' userInfos'. Например, если элемент 'users'' Item1' относится к идентификатору, 'Item2' относится к имени и т. Д. – Dzienny

1

Попробуйте

var list = (from u in context.users 
         join ud in context.UserDetails on u.Id equals ud.UId 
         select new 
         { 
          u.Id, 
          u.Name, 
          u.Age, 
          ud.Key, 
          ud.Value 
         }); 

      var finallist = list.GroupBy(x => new { x.Id, x.Name,x.Age}).Select(x => new 
       { 
        x.Key.Id, 
        x.Key.Name, 
        x.Key.Age, 
        Height = x.Where(y => y.Key == "Height").Select(y => y.Value).FirstOrDefault(), 
        Eyes = x.Where(y => y.Key == "Eyes").Select(y => y.Value).FirstOrDefault(), 
        Hair = x.Where(y => y.Key == "Hair").Select(y => y.Value).FirstOrDefault() 
       }).ToList(); 
2

Прежде всего я сгруппировал данные пользователя данные используя функцию (я переименовал свойство Key с Feature во избежание путаницы) & UId, тогда я использовал групповое объединение, чтобы объединить оба результата, используя into g. Наконец, получен результат с использованием указанной функции.

var result = from user in users 
      join detail in details.GroupBy(x => new { x.UId, x.Feature }) 
      on user.Id equals detail.Key.UId into g 
      select new 
     { 
      Id = user.Id, 
      Name = user.Name, 
      Age = user.Age, 
      Height = g.FirstOrDefault(z => z.Key.Feature == "Height") != null ? 
       g.First(z => z.Key.Feature == "Height").First().Value : String.Empty, 
      Eyes = g.FirstOrDefault(z => z.Key.Feature == "Eyes") != null ? 
       g.First(z => z.Key.Feature == "Eyes").First().Value : String.Empty, 
      Hair = g.FirstOrDefault(z => z.Key.Feature == "Hair") != null ? 
       g.First(z => z.Key.Feature == "Hair").First().Value : String.Empty, 
     }; 

Я получаю следующий вывод: -

enter image description here

Вот полный Working Fiddle.

Смежные вопросы