2013-07-31 10 views
7

Mam tabeli o nazwie Languagemaster mający poniżej rekorduJak konwertować Row Kolumna w Linq i SQL

language keyName keyValue 
English City AA 
Swedish City AAswedish 
German  City AAger 
Chines  City AAchines 
French  City AAfr 
Spanish City AAspanish 

jak konwertować Languagemaster Tabela poniżej tabeli

keyName English Swedish German Chines French Spanish    
City  AA  AAswedish AAger AAchines AAfr AAspanish 

daj wiem jak pisać Query zarówno w SOL, jak i LinQ.

+0

możliwe duplikat [LINQ swapowych kolumn na wiersze] (http://stackoverflow.com/questions/6950495/linq-swap-columns-into-rows) – Fals

+0

wygląda tak jak chcesz grupować kolumny według wartości 'keyName'. – YD1m

Odpowiedz

16

UPDATE: Utworzono następującą metodę ogólną, które można zbudować stół obrotowy z każdej kolekcji

public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
    this IEnumerable<T> source, 
    Func<T, TColumn> columnSelector, 
    Expression<Func<T, TRow>> rowSelector, 
    Func<IEnumerable<T>, TData> dataSelector) 
{ 
    DataTable table = new DataTable(); 
    var rowName = ((MemberExpression)rowSelector.Body).Member.Name; 
    table.Columns.Add(new DataColumn(rowName)); 
    var columns = source.Select(columnSelector).Distinct(); 

    foreach (var column in columns) 
     table.Columns.Add(new DataColumn(column.ToString())); 

    var rows = source.GroupBy(rowSelector.Compile()) 
        .Select(rowGroup => new { 
         Key = rowGroup.Key, 
         Values = columns.GroupJoin(
          rowGroup, 
          c => c, 
          r => columnSelector(r), 
          (c, columnGroup) => dataSelector(columnGroup)) 
        }); 

    foreach (var row in rows) { 
     var dataRow = table.NewRow(); 
     var items = row.Values.Cast<object>().ToList(); 
     items.Insert(0, row.Key); 
     dataRow.ItemArray = items.ToArray(); 
     table.Rows.Add(dataRow); 
    } 

    return table; 
} 

Zastosowanie:

var table = Languagemaster.ToPivotTable(
       item => item.language, 
       item => item.keyName, 
       items => items.Any() ? items.First().keyValue : null); 

ma trzy parametry:

  • kolumnę selektor właściwości, który wybiera kolumny (tj. co będzie w nagłówkach kolumn) w twoim przypadku są to różne wartości języków, ale może to być cokolwiek innego, jak data.
  • selektor właściwości wiersza - jest wartością, która pojawi się w nagłówkach wierszy, z której każdy wiersz będzie powiązany. Pamiętaj - to wyrażenie, a nie zwykły delegat. Potrzebujemy go, aby ustawić nazwę kolumny pierwszej kolumny.
  • selektor danych - jest to metoda, która będzie uruchamiana na zgrupowanych danych dla każdej komórki. To znaczy. w twoim przypadku po prostu wybieramy keyValue właściwość pierwszego elementu w grupie. Ale mogą to być przedmioty o numerach items => items.Count() lub cokolwiek innego.

Wynik:

enter image description here


ORIGINAL ODPOWIEDŹ:

To zapytanie zwróci pivot dla Twoich danych. Każda pozycja w zapytaniu będzie miał Name (czyli „Miasto” w przykładzie) oraz listę wartości - wartość dla każdej kolumny obrotu (czyli dla każdego języka będziemy mieć wartość zawierającą nazwę języka jako Column i Value)

var languages = Languagemaster.Select(x => x.language).Distinct(); 
var query = from r in Languagemaster 
      group r by r.keyName into nameGroup 
      select new { 
       Name = nameGroup.Key, 
       Values = from lang in languages 
         join ng in nameGroup 
           on lang equals ng.language into languageGroup 
         select new { 
          Column = lang, 
          Value = languageGroup.Any() ? 
            languageGroup.First().keyValue : null 
         } 
      }; 

Jak zbudować tabelę danych z tego zapytania

DataTable table = new DataTable(); 
table.Columns.Add("keyName"); // first column 
foreach (var language in languages) 
    table.Columns.Add(language); // columns for each language 

foreach (var key in query) 
{ 
    var row = table.NewRow(); 
    var items = key.Values.Select(v => v.Value).ToList(); // data for columns 
    items.Insert(0, key.Name); // data for first column 
    row.ItemArray = items.ToArray(); 
    table.Rows.Add(row); 
} 
+0

Mam nadzieję, że planujesz używać tego tylko dla małych zestawów danych. –

+0

@AlW manipulowanie ogromnymi zbiorami danych w pamięci nie jest dobrym pomysłem. –

+1

Naprawdę jest to świetne rozwiązanie .. wiele dzięki – user1624306