【问题标题】:How to convert rows to columns in LINQ如何在 LINQ 中将行转换为列
【发布时间】:2019-09-27 02:28:54
【问题描述】:

我在图像中有第一个输出,我想使用 LINQ Core 将其转换为图像中的第二个输出。 LINQ 中是否有直接 unpivot 选项。

我可以用 SQL 编写 PIVOT 和 UNPIVOT 的代码。但无法在 LINQ 中找到相同的方法。

我有以下相同的 SQL 查询:

SELECT ResourceName,
            max(ENText)as ENText,
            max(FRText)as FRText,
            max(ZHText)as ZHText,
            max(DEText)as DEText,
            max(ITText)as ITText,
            max(JAText)as JAText,
            max(PTText)as PTText,
            max([PT-BRText]) as [PT-BRText],
            max(RUText) as RUText,
            max(ESText) as ESText,
            max(SVText) as SVText  into #temp 
            FROM   
GenericLanguageTranslation 
PIVOT  
(  
max(Translation) FOR LanguageID IN (
            ENText,
            ZHText,
            FRText,
            DEText,
            ITText,
            JAText,
            PTText,
            [PT-BRText],
            RUText,
            ESText,
            SVText)
) AS Tab2  
group by ResourceName
order by 1

select * from #temp
SELECT NEWID() as Id,ResourceName, [LanguageID],[Translation]-- into #GenericLanguageTranslation
FROM #temp
UNPIVOT
(
       [Translation]
       FOR [LanguageID] IN 
       (
            ENText,
            ZHText,
            FRText,
            DEText,
            ITText,
            JAText,
            PTText,
            [PT-BRText],
            RUText,
            ESText,
            SVText

       )
) AS UnpivotTranslation

【问题讨论】:

  • @ElandaloussiIshrak 我已经引用了该链接并实现了相同的链接及其工作,但我正在寻找更通用的解决方案或至少一个冗余代码较少的解决方案。
  • 查看我的new answer 来回答这个问题。

标签: c# linq pivot unpivot dynamic-linq-core


【解决方案1】:

如果您愿意使用反射,并且愿意在客户端进行反透视,请按照以下步骤操作。

返回类包括透视数据和非透视字段:

public class UnpivotData {
    public Guid Id { get; set; }
    public string ResourceName { get; set; }
    public string LanguageID { get; set; }
    public string Translation { get; set; }

    public UnpivotData() => Id = Guid.NewGuid();

    public UnpivotData ShallowCopy() {
        var ans = (UnpivotData)this.MemberwiseClone();
        ans.Id = Guid.NewGuid();
        return ans;
    }
}

然后是进行反透视的扩展方法:

public static class IEnumerableExt {
    public static IEnumerable<UnpivotData> Unpivot<T>(this IEnumerable<T> src, string[] pivotFieldNames, string unPivotName, string unPivotValue, Func<string, bool> unpivotFieldNameFn) {
        var srcPIs = typeof(T).GetProperties();
        var srcPivotPIs = srcPIs.Where(pi => pivotFieldNames.Contains(pi.Name));
        var ansPIs = typeof(UnpivotData).GetProperties();
        var ansPivotPIs = ansPIs.Where(pi => pivotFieldNames.Contains(pi.Name));
        var srcAnsPivotPIs = srcPivotPIs.Zip(ansPivotPIs, (spi, api) => new { spi, api }).ToList();
        var srcUnpivotPIs = srcPIs.Where(pi => unpivotFieldNameFn(pi.Name)).ToList();
        var unPivotNamePI = ansPIs.First(pi => pi.Name == unPivotName);
        var unPivotValuePI = ansPIs.First(pi => pi.Name == unPivotValue);

        foreach (var d in src) {
            var ansbase = new UnpivotData();
            foreach (var sapi in srcAnsPivotPIs)
                sapi.api.SetValue(ansbase, sapi.spi.GetValue(d));

            foreach (var spi in srcUnpivotPIs) {
                var ans = ansbase.ShallowCopy();
                unPivotNamePI.SetValue(ans, spi.Name);
                unPivotValuePI.SetValue(ans, spi.GetValue(d));

                yield return ans;
            }
        }
    }
}

现在您可以取消透视数据了:

var result = genericLanguageTranslation.AsEnumerable().Unpivot(new[] { "ResourceName" }, "LanguageID", "Translation", fn => fn.EndsWith("Text"));

【讨论】:

    猜你喜欢
    • 2022-01-26
    • 2013-08-01
    • 2017-06-28
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2013-12-11
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多