如何在Linq和SQL中将行转换为列

时间:2013-07-31 13:35:15

标签: .net asp.net-mvc linq

我有一张名为 Languagemaster 的表格,其记录低于记录

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

如何将 Languagemaster 表转换为下表

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

请告诉我如何在SOL和LinQ中编写查询。

3 个答案:

答案 0 :(得分:23)

更新:我创建了以下通用方法,可以从任何集合构建数据透视表

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;
}

用法:

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

它有三个参数:

  • 列属性选择器选择列(即列标题中的内容),在您的情况下,它是不同的语言值,但它可以是其他任何内容,例如date。
  • 行属性选择器 - 是一个将出现在行标题中的值,这是每行与之相关的内容。请记住 - 它是表达式,而不是简单的委托。我们需要它来设置第一列的列名。
  • 数据选择器 - 这是一种将在每个单元格的分组数据上运行的方法。即在您的情况下,我们只选择组中第一项的keyValue属性。但它可能是项目计数items => items.Count()或其他任何内容。

结果:

enter image description here


原始回答:

此查询将返回您的数据的数据透视。查询中的每个项目都有Name(即示例中的“城市”)和值列表 - 每个数据透视列的一个值(即,对于每种语言,我们将使用包含语言名称Column的值和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
                         }
            };

如何从此查询构建数据表

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);
}

答案 1 :(得分:0)

这是一个基于多列对数据进行分组的代码。

$(window).on('scroll', function(event) {
    var scrollValue = $(window).scrollTop();
    if ( scrollValue > 70) {
         $('.navbar-sticky').addClass('fixed-top');
    }else{
       $('.navbar-sticky').removeClass('fixed-top');
    }
});

答案 2 :(得分:0)

public static DataTable XToPivotTable<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();

      if (rowSelector.Body is NewExpression) {
        var rowNames = ((NewExpression)rowSelector.Body).Members.ToList();
        rowNames.ForEach(s => table.Columns.Add(new DataColumn(s.Name, s.DeclaringType.GetProperty(s.Name).PropertyType)));
      } else {
        var rowName = ((MemberExpression)rowSelector.Body).Member;
        table.Columns.Add(new DataColumn(rowName.Name, rowName.DeclaringType.GetProperty(rowName.Name).PropertyType));
      }

      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(rg => new {
          rg.Key,
          Values = columns.GroupJoin(rg, c => c, r => columnSelector(r), (c, cg) => dataSelector(cg))
        });

      foreach (var row in rows) {
        var dataRow = table.NewRow();
        var items = TypeDescriptor.GetProperties(typeof(TRow)).Cast<PropertyDescriptor>().Select(s => s.GetValue(row.Key)).ToList();
        items.AddRange(row.Values.Cast<dynamic>());
        dataRow.ItemArray = items.ToArray();
        table.Rows.Add(dataRow);
      }

      return table;
    }