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

标签 .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 中编写查询。

最佳答案

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

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

它有三个参数:

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

结果:

enter image description here

<小时/>

原答案:

此查询将返回您的数据的数据透视表。查询中的每个项目都将具有 Name (即示例中的“City”)和值列表 - 每个数据透视列都有一个值(即对于每种语言,我们将包含包含语言名称为 的值列)

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

关于.net - 如何在 Linq 和 SQL 中将行转换为列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17971921/

相关文章:

asp.net - Web 事件提供程序 'EventLogProvider' 引发了以下异常

.net - FIDO 2.0 WebAuthn 库能否用于与 FIDO 1.0 UAF 通信?

c# - 确定窗口是否处于帮助模式

asp.net-mvc - 在 ASP.NET Core 中发现通用 Controller

asp.net-mvc - 在MVC项目中创建区域

c# - 从 Base64 字符串创建图像时 GDI+ 中出现一般错误

c# - 随机重新排序 LINQ 集合的最快方法?

.net - Entity Framework 外键到非主键字段

Linq选择不同的列

c# - 通过 linq DELETE 抛出并发异常而没有并发